LLM function calling and tool use patterns. Use when enabling LLMs to call external tools, defining tool schemas, implementing tool execution loops, or getting structured output from LLMs.
Scanned 2/12/2026
Install via CLI
openskills install yonatangross/orchestkit---
name: function-calling
description: LLM function calling and tool use patterns. Use when enabling LLMs to call external tools, defining tool schemas, implementing tool execution loops, or getting structured output from LLMs.
tags: [llm, tools, function-calling, structured-output]
context: fork
agent: llm-integrator
version: 1.0.0
author: OrchestKit
user-invocable: false
---
# Function Calling
Enable LLMs to use external tools and return structured data.
## Basic Tool Definition (2026 Best Practice)
```python
# OpenAI format with strict mode (2026 recommended)
tools = [{
"type": "function",
"function": {
"name": "search_documents",
"description": "Search the document database for relevant content",
"strict": True, # ← 2026: Enables structured output validation
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query"
},
"limit": {
"type": "integer",
"description": "Max results to return"
}
},
"required": ["query", "limit"], # All props required when strict
"additionalProperties": False # ← 2026: Required for strict mode
}
}
}]
# Note: With strict=True:
# - All properties must be listed in "required"
# - additionalProperties must be False
# - No "default" values (provide via code instead)
```
## Tool Execution Loop
```python
async def run_with_tools(messages: list, tools: list) -> str:
"""Execute tool calls until LLM returns final answer."""
while True:
response = await llm.chat(messages=messages, tools=tools)
# Check if LLM wants to call tools
if not response.tool_calls:
return response.content
# Execute each tool call
for tool_call in response.tool_calls:
result = await execute_tool(
tool_call.function.name,
json.loads(tool_call.function.arguments)
)
# Add tool result to conversation
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result)
})
# Continue loop (LLM will process tool results)
async def execute_tool(name: str, args: dict) -> any:
"""Route to appropriate tool implementation."""
tools = {
"search_documents": search_documents,
"get_weather": get_weather,
"calculate": calculate,
}
return await tools[name](**args)
```
## Structured Output (Guaranteed JSON)
```python
from pydantic import BaseModel
class Analysis(BaseModel):
sentiment: str
confidence: float
key_points: list[str]
# OpenAI structured output
response = await client.beta.chat.completions.parse(
model="gpt-5.2",
messages=[{"role": "user", "content": "Analyze this text..."}],
response_format=Analysis
)
analysis = response.choices[0].message.parsed # Typed Analysis object
```
## LangChain Tool Binding
```python
from langchain_core.tools import tool
from pydantic import BaseModel, Field
@tool
def search_documents(query: str, limit: int = 5) -> list[dict]:
"""Search the document database.
Args:
query: Search query string
limit: Maximum results to return
"""
return db.search(query, limit=limit)
# Bind to model
llm_with_tools = llm.bind_tools([search_documents])
# Or with structured output
class SearchResult(BaseModel):
query: str = Field(description="The search query used")
results: list[str] = Field(description="Matching documents")
structured_llm = llm.with_structured_output(SearchResult)
```
## Parallel Tool Calls
```python
# OpenAI supports parallel tool calls
response = await llm.chat(
messages=messages,
tools=tools,
parallel_tool_calls=True # Default in GPT-5 series
)
# Handle multiple calls in parallel
if response.tool_calls:
results = await asyncio.gather(*[
execute_tool(tc.function.name, json.loads(tc.function.arguments))
for tc in response.tool_calls
])
```
**⚠️ 2026 Compatibility Note:**
```python
# Structured outputs with strict=True may not work with parallel_tool_calls
# If using strict mode schemas, disable parallel calls:
response = await llm.chat(
messages=messages,
tools=tools_with_strict_true,
parallel_tool_calls=False # Required for strict mode reliability
)
```
## Key Decisions
| Decision | Recommendation |
|----------|----------------|
| Tool count | 5-15 max (more = confusion) |
| Description length | 1-2 sentences |
| Parameter validation | Use Pydantic/Zod |
| Error handling | Return error as tool result |
| **Schema mode** | **`strict: true` (2026 best practice)** |
| Output format | Structured Outputs > JSON mode |
| Parallel calls | Disable with strict mode |
## Common Mistakes
- Vague tool descriptions (LLM won't know when to use)
- No input validation (LLM sends bad params)
- Missing error handling (crashes on tool failure)
- Too many tools (LLM gets confused)
## Related Skills
- `agent-loops` - Multi-step tool use with reasoning
- `llm-streaming` - Streaming with tool calls
- `structured-output` - Complex output schemas
## Capability Details
### tool-definition
**Keywords:** tool, function, define tool, tool schema, function schema
**Solves:**
- Define tools with clear descriptions
- Create JSON schemas for tool parameters
- Document tool behavior for LLM
### tool-execution-loop
**Keywords:** execution loop, tool call, agent loop, run tool
**Solves:**
- Implement tool execution loops
- Handle multiple tool calls
- Process tool results
### structured-output
**Keywords:** structured output, JSON output, typed response, response schema
**Solves:**
- Get structured JSON from LLM
- Enforce output schemas
- Parse and validate responses
### parallel-tool-calls
**Keywords:** parallel, concurrent, multiple tools, batch tools
**Solves:**
- Execute multiple tools in parallel
- Handle concurrent tool results
- Optimize tool call latency
### strict-mode-schemas
**Keywords:** strict mode, strict schema, additionalProperties, required fields
**Solves:**
- Enforce strict JSON schemas
- Prevent extra fields in output
- Ensure schema compliance
No comments yet. Be the first to comment!