tools field of every request leads to Tool Definition Bloat: every request carries the descriptions and parameter schemas of all tools, driving up token usage, and the more candidate tools there are, the more likely the model picks the wrong tool or constructs invalid call arguments.
Dynamically Loaded Tools let you inject tools on demand during a conversation: start with only a few core tools, and insert additional tools into messages when the conversation actually needs them — reducing token usage and improving tool-selection accuracy at the same time. For the reasoning behind this design (lazy loading, tool registry) and combined practices, see Kimi K3 API Tool Calling Best Practices.

Inject tool declarations into messages
Insert a message withrole set to system into messages, and declare the tools to load through that message’s tools field. The declaration format is identical to the top-level tools field of the request, and must contain the complete tool definition (name, description, parameters):
- A
systemmessage carryingtoolshas the same standing as ordinary input messages: the tools become visible to the model starting from the position where the message appears in themessageslist; - Dynamically loaded tools coexist with the global tools declared in the top-level
toolsfield — the model can see both; - A dynamically injected tool declaration must be a complete tool definition; you cannot pass only a tool name or reference a tool already declared globally.
- curl
- python
Implementing tool search with dynamic loading
There is no dedicated tool-search API. If you have a large tool inventory, you can implement tool search yourself by combining a custom search tool with dynamically loaded tools:- Declare only a single
search_toolsfunction in the top-leveltoolsfield, implemented by your backend, which returns matching tool names and summaries for a given keyword; - In the system prompt, advertise the searchable keywords (e.g. a tool catalog or domain tags) so the model knows to call
search_toolsfirst when it needs a tool; - Based on what
search_toolsreturns, your application inserts the full declarations of the matching tools intomessagesvia asystemmessage carrying atoolsfield; - The model can then call these newly loaded tools in subsequent generations.
Notes
- Dynamic tool declarations apply per request and are not retained by the server. The client decides whether to include them again in the next request:
- Keep the declaration: the tool remains available, and the unchanged prefix is more likely to hit the cache;
- Omit the declaration: the declaration no longer applies. If the tool is not declared elsewhere, the model cannot call that tool. Because
messageshas changed, the prefix after that point may miss the cache.
- Dynamic tool declarations use exactly the same format as global
toolsdeclarations — you maintain a single schema, keeping migration cheap; - Appending a dynamic tool declaration to the end of
messagesdoes not affect the cached prefix. Removing or modifying an earlier tool declaration may affect cache hits after the point of change. Declaring global tools in the top-leveltoolsfield does not affect cache hits either; - A
systemmessage carryingtoolsalso consumes context length, so only inject the tools the current conversation genuinely needs; - Dynamically loaded tools are currently supported only on
kimi-k3; on other models (e.g.kimi-k2.6) the request fails with atokenization failederror; - A
systemmessage carryingtoolsmust not also carry acontentfield, otherwise the request fails with a 400 error (cannot be used with content); with the OpenAI SDK you can pass thetoolsfield through directly inmessages— noextra_bodyneeded.
Related reading
- Kimi K3 API Tool Calling Best Practices: combined practices for dynamic loading, tool_choice, and thinking effort
- Tool Choice: constrain the model’s tool-calling behavior with
tool_choice - Use Kimi API for Tool Calls: the complete tool-calling workflow and examples
- Model Parameter Reference: per-model support for parameters such as
tool_choice