Tool calling becomes unreliable and expensive when an LLM has too many tools or receives large, overly general results.
2
LLMs are often better at writing code than at selecting and parameterizing static function calls, so agents should use code generation more directly.
3
A sandbox with evaluation, libraries, and generated interfaces can turn one broad capability into reusable tools and a working application.
Summary
Manuel Odendahl argues that MCPs and conventional tool calling give LLM applications a narrow mental model. A model receives static schemas, chooses one function, emits arguments, and gets the full result back. This works, but many tools make selection and parameter generation unreliable, while large responses waste time and tokens. Odendahl proposes using the model's strength at writing code instead. An eval capability can let it inspect schemas, write SQL or JavaScript, compose several operations, and create reusable functions or views. Those functions can become a library rather than thousands of separately exposed tools. He also wants the host application to let users edit tool inputs and outputs through richer interfaces, including controls for files, memories, and filters. His prototype uses a JavaScript sandbox with SQLite and web-server libraries. It can generate database functions, REST endpoints, and a CRM interface. The talk's central idea is recursive: ask the model to write the code that solves the task, then preserve and reuse that code.
Tool calling is easy to wire up, but static schemas constrain it
Odendahl describes the usual tool-calling loop: the application places tool schemas in the model context, the model emits a structured call, deterministic code invokes an API, and the result goes back for another inference. MCP makes it possible to download tools for GitHub, Blender, files, or even a room-temperature sensor. He says the experience feels magical once a few tools are connected. The limitation appears when the model has too many choices. With 100 tools, it may confuse a weather lookup with an internet search, misunderstand a schema, or provide the wrong parameters.
Large tool inputs and outputs make simple tasks slow and expensive
Tool arguments are generated as tokens, even when the needed information is already present higher in the context. A document fragment may be copied into a search call, and a weather request repeats 'San Francisco'. Tool responses create the same problem in reverse. Asking only for wind speed can still return a large JSON object containing dates and other conditions. Odendahl gives a CRM example where a request for OpenAI's contact information returns a list of 36 companies, even though the application needs one email address. Broad responses support fuzzy questions, but they can also produce 20,000 tokens, a long wait, and unnecessary cost.
Odendahl suggests passing chat history, memories, and file information along with a tool call. A tool could see that the same request has already been made 15 times and reuse earlier arguments. A weather tool could inspect a stored location memory and infer San Francisco without requiring the model to repeat it. Attached files could be passed directly, through a path, or through metadata. He acknowledges that modalities, graph structures, and security make this difficult. Protocol designers would need to handle images, files, memories, and application-specific data without recreating the heavy engineering of older semantic-web systems.
Users should be able to edit calls and results before the model continues
The normal approval interaction is too limited for Odendahl. He proposes a UI where a user can inspect and edit the model's arguments before a call runs. A misspelled company name or an unexpected target could be corrected without restarting the agent. Users could also edit the returned data before it is added to the model context. For a database query that returns 10,000 records, manually filtering the result may be faster and cheaper than asking the model to process it. His prototypes imagine sliders, drop-downs, file attachments, filters, and a way to rerun a call with modified inputs.
Generated code is often a better interface than static function calls
Odendahl says LLMs can produce poems, terminal commands, applications, and code for newly built APIs, yet often struggle with ordinary function-call parameters. SQL is already code, and a file-edit operation can also be expressed as code. Instead of exposing a fixed CRM MCP with a narrow schema, an application could give the model a CRM library and let it write a function such as getting a company's contact information. The model can add loops, combine operations, and create a task-specific tool at the moment it is needed. He connects this approach to the Voyager paper and a paper about code producing better tool actions.
His proposed MCP needs an eval capability rather than a large collection of individual functions. In the SQL example, the model can inspect customer and order tables, read their schemas, write a join and aggregation, and return a deterministic query result. If the first attempt fails because of a field or date format, it can revise the code. Odendahl contrasts this with a generic tool that may return thousands of invoice rows and leave the model to perform arithmetic over thousands of tokens. Once a query works, the application can save it as a view or reusable function, so later requests need less schema exploration.
Libraries turn generated functions into reusable capabilities
Odendahl proposes exposing a preconfigured library instead of a GitHub MCP with a fixed list of calls. The model could import the CRM library and generate richer operations from its functions. He claims models can work with very large APIs when those APIs are available as code, while the same capabilities become difficult when exposed as tool calls. A library can hide authentication details, combine lower-level operations, and support task-specific functions. The result is a set of code that both the model and the engineer can inspect and reuse.
A sandbox can generate tools, APIs, and user interfaces
Odendahl demonstrates a prototype written in Go with a JavaScript sandbox, a SQLite library, and a web-server library. The sandbox exposes an eval call and lets generated JavaScript register REST handlers. In his CRM example, the model inspects the database, writes queries, creates functions such as company lookup and search, and registers endpoints. It then generates HTML and CSS handlers for a website. The result is a working CRM that can be used without the LLM after generation. He presents this as a way to move from a small tool widget to an application built from generated code.
Recursive code generation changes the agent mental model
Odendahl asks engineers to think recursively. Once an LLM writes code for a task, it can write code that writes that code. His JavaScript sandbox contains loaded libraries that can produce further libraries and APIs for reuse in other systems. The model is therefore more than an agent choosing from predefined tools. In his framing, the LLM writes the code that performs the work, and that code can create more capabilities. The practical instruction is simple: when asking the model to do something, also consider asking it to write the code that does it.
"Why don't we leverage that instead of being stuck with this like you can only call functions, you can only call functions with this schema that we've given you and it's static and you can't even modify it."14:28
Who should watch
You are building an agent with many MCP tools and are seeing confused tool selection, oversized responses, or high latency.
You want to let an LLM work with a database or API by generating code instead of maintaining a large collection of static schemas.
You design an LLM host interface and want users to inspect, edit, filter, or rerun model-generated operations.