No Custom Function Calling: Understanding the Limitation
On this page
A Structural Limitation
If you’re used to declaring your own functions and letting the model decide when to call them, get ready to change your approach: Grok’s multi-agent system doesn’t support custom function calling. This isn’t a configuration detail; it’s an architectural constraint that affects how you structure your application. Better to find out now than after writing three hundred lines of function schemas.
The Exact Boundary
What works are the five built-in tools from the previous lesson: web_search for real-time web search, x_search for the X platform, code_execution to run Python, collections_search for your indexed collections, and Remote MCP for external tools via the MCP protocol. Nothing else works. Functions defined in your code, custom schemas, and calls to your own APIs via the function calling mechanism are all refused.
Specifically, the declaration below, perfectly valid with a standard model, has no effect in multi-agent.
# DOES NOT WORK with multi-agent
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the weather",
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}}
}
}
]
Where This Constraint Comes From
The reason comes down to coordination. With a single model, the function calling loop is clear: the model requests a call, your code executes it, you return the result, the model continues. Now introduce four or sixteen agents working in parallel, and questions pile up. Which one decides to call the function? What if two agents call the same function simultaneously with different arguments? How does the leader synthesize results obtained by sub-agents whose reasoning it didn’t follow?
Built-in tools are designed for this context and know how to behave correctly when multiple agents request them at once. Your functions, however, were written assuming a single caller. This limitation reflects that design difference rather than a temporary shortfall.
Expose Your APIs via an MCP Server
The cleanest solution is to not workaround it at all, but to use the intended door. If you need to call your own services, expose them via an MCP server: agents then handle them like native tools, with the necessary concurrency management. It’s a bit more work upfront than a function declaration, but it remains the only way to bring your information system into the search loop.
Separate Research from Action
Second strategy, often the right one when your functions trigger side effects: split the process in two. The multi-agent does what it knows how to do, search and analyze; a standard model takes over for the part that calls your APIs.
# Step 1: multi-agent research
chat = client.chat.create(
model="grok-4.20-multi-agent-0309",
agent_count=4,
tools=[web_search()],
)
chat.append(user("Find the best Italian restaurants in Paris"))
research_result = ""
for response, chunk in chat.stream():
if chunk.content:
research_result += chunk.content
# Step 2: action with standard model + function calling
# Use grok-4.5 or another model that supports function calling
This separation has an underestimated advantage: it lets you inspect and validate the search result before an irreversible action is triggered. An agent booking a table based on unchecked research is rarely a good idea.
Enrich Before, Process After
Third approach, the lightest: call your APIs outside the conversation, upstream to enrich the prompt, downstream to exploit the response. Many needs believed to require function calling actually boil down to injecting the right data at the right time.
# Pre-processing: enrich context
user_data = my_api.get_user_profile(user_id)
context = f"User profile: {user_data}"
# Multi-agent with enriched context
chat.append(user(f"{context}\n\nAnalyze options matching this profile"))
The customer profile, order history, or budget constraints don’t need to be retrieved by the model: you already know them, just give them to it. Finally, keep in mind that the API is in beta and this limitation could evolve—all the more reason to isolate the multi-agent part of your code behind an interface you can evolve without rewriting everything.
Key Takeaways
- Custom function calling is not supported with multi-agent
- Only built-in tools (web_search, x_search, code_execution, collections_search, Remote MCP) work
- Use Remote MCP to expose your own APIs to agents
- Adopt a two-step architecture if you need function calling
- This limitation may evolve in future versions (API beta)