AI Engineer Summit 2025

Tool Calling Is Not Just Plumbing for AI Agents

Roy Derks25:18

Read the talk

Tool Calling Is Not Just Plumbing for AI Agents

Reliable agents need tools with clear contracts, deliberate execution boundaries and reusable business logic—not just a framework that can call functions.

From a talk by Roy Derks

Before you start: Familiarity with API calls, JSON and basic TypeScript will help; the article introduces the agent orchestration and GraphQL concepts it uses.

Can your tools survive a change of agent framework?

If you replace your agent framework, how much of your tool implementation can you keep? Tool calling can look like plumbing: something to assemble yourself or delegate to a professional. But the useful engineering goal is more specific—build tools that are robust and reusable enough to move between frameworks. Regular tool calling, embedded execution and standalone platforms offer different ways to arrange that boundary.

Roy Derks approaches this as an application developer. After working at and founding startups, he joined IBM through an acquisition; his background includes GraphQL, web development and React. That experience matters because tools are application software: they connect model decisions to systems with their own interfaces, data and failure modes.

A typical agent loop starts with a user request and brings together a model, memory and tools. Developers often concentrate on selecting the framework, then use its bundled tools or extend its interfaces to implement their own. The tool layer can consequently become tightly coupled to the agent that first needed it.

Diagram with an agent linked by bidirectional arrows to a user, LLMs, memory and tools; tools connect to APIs, a database and a document.Open full source frame
An agent connects the user, LLMs, memory and tools.

In Derks’s experience, tools are often the first thing to break. The model may call a tool incorrectly, choose the wrong one, or reach an implementation whose internal setup is broken. These are distinct failures: better tool selection does not repair a misconfigured backend. Agent reliability depends on the tools as well as the orchestration. As models improve, the application layer still needs deliberate software engineering to make their capabilities useful.

0:040:14
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:04 · section reference included

A travel question becomes retrieval and calculation

Having moved from Amsterdam to San Francisco, Derks asks how far the Moon’s orbit is when expressed as trips between the two cities. He reports a chat answer of about forty-four round trips. That number remains an illustrative chat response: the explanation shifts from orbital travel to Earth–Moon separation, which NASA defines as a different quantity. The example is useful for its decomposition, not as a settled distance calculation.

A model might answer from information represented in its training data. With tools, the work becomes explicit:

  1. Search for the Earth–Moon distance.
  2. Search for the distance between Amsterdam and San Francisco airports.
  3. Calculate the requested comparison from the retrieved values.

The final step might be performed by the model or delegated to a calculation tool. Either way, retrieving the right quantities and deciding what they mean are separate responsibilities.

Tool Calling slide showing a question and answer above Agent + LLM, linked to External APIs, with steps to search Earth–Moon distance, search AMS–SFO distance and calculate.Open full source frame
Tool calling combines two distance searches with calculation.

Now extend the question: how many days would those trips take, and would flying them be quicker than a lunar orbit? Derks estimates ten to twelve hours per flight, before airport waits and return flights. A distance ratio alone no longer answers the question; the agent needs more inputs and assumptions. Web search, a geographical database or another external API can supply facts, while JavaScript, Python or Wolfram Alpha can perform calculations. Implementing those connections is only part of the work—the definitions must also tell the model when and how to use them.

4:044:11
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:04 · section reference included

A tool definition is a behavioral contract

Start with a simple name. Then give the tool a description that helps the model decide when to select it and how to use it. Derks compares that description to a system prompt: a substantial tool may need considerably more guidance than “calculate something from two variables.” Repeating instructions across the system prompt and tool descriptions also means there are multiple places where behavior is being shaped.

Input parameters describe what a call requires. An output schema describes what the next step can expect back. That second contract becomes especially valuable when tools are chained: the consumer needs to know the shape of the producer’s result, not merely that something will return. Schemas support type safety and structured outputs, provided the implementation actually enforces them.

For a customer-count tool, the invocation carries a name and arguments such as a country filter. The result might arrive as a string containing JSON that the application decodes. The following TypeScript makes that small contract concrete, including a check at the serialization boundary:

typescript

type CustomerCountCall = {
  name: "customer_count";
  arguments: { country: string };
};

type CustomerCountResult = { count: number };

const call: CustomerCountCall = {
  name: "customer_count",
  arguments: { country: "NL" },
};

function decodeCustomerCount(text: string): CustomerCountResult {
  const value: unknown = JSON.parse(text);
  if (
    typeof value !== "object" ||
    value === null ||
    !("count" in value) ||
    typeof value.count !== "number" ||
    !Number.isSafeInteger(value.count) ||
    value.count < 0
  ) {
    throw new Error("Invalid customer-count result");
  }
  return { count: value.count };
}

String serialization belongs to the illustrated integration, not to every tool protocol; even the historical MCP tools specification allowed text, images and embedded resources as results.

A fixed customer-count function is not the only possible interface. A tool can instead expose access to a database or API and accept SQL or GraphQL generated by the model. That moves some of the work from selecting a narrowly defined operation to constructing a query—a trade-off that becomes more significant as the tool catalog grows.

6:046:14
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

6:04 · section reference included

Traditional calling puts the loop in your application

Where does the logic that chooses, dispatches and repeats tool calls live? Derks tentatively traces the traditional-versus-embedded terminology to a Cloudflare post. Cloudflare’s embedded function calling article uses “embedded” specifically for execution alongside inference in Workers AI; here, Derks uses it more broadly for orchestration enclosed within an agent framework.

In traditional calling, the application owns the exchanges:

  1. The chat client sends the user’s question to the server-side agent application.
  2. The application sends a prompt and tool information to the model.
  3. The model returns a proposed tool call.
  4. Application code dispatches the corresponding callback.
  5. The application sends the tool result back to the model.
  6. Further calls repeat the cycle until an answer can return to the client.

The model’s request and the tool’s execution are separate events. The callback runs because application code interprets and dispatches the request.

In the LangChain example using IBM watsonx models, the developer defines tools and callbacks, examines returned messages for tool-call content, parses it and invokes the registered implementation. Derks describes filtering messages by role in that integration. The same application also has to handle retries and errors. This arrangement exposes the execution loop directly, but makes its operational responsibilities yours.

8:178:26
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

8:17 · section reference included

Embedded calling delegates orchestration

With embedded tool calling, the client submits the question to an agent that already contains the orchestration. That agent communicates with the model, invokes tools and returns an answer. From the caller’s perspective, prompt and tools enter a closed component; the intermediate exchanges no longer appear in its application logic.

The recording’s LangChain example supplies a model, tools and a prompt to a ReAct agent factory, then uses an agent executor to run it. The functionality resembles the explicit loop, but the framework contains the dispatch machinery. Derks presents this as an easier starting point, with error and retry handling delegated to the framework; the precise guarantees still depend on the chosen implementation.

ResponsibilityTraditional callingEmbedded calling
Model/tool exchangesApplication loopFramework loop
Callback dispatchExplicit application codeAgent machinery
Errors and retriesApplication handles themFramework policy
Execution controlDirectThrough exposed interfaces

Derks’s black-box criticism concerns the control available at this boundary: how tools execute, how decisions are made and how results are formatted. Descriptions and callbacks still influence behavior, but the enclosing loop is no longer code the caller directly manages.

11:1811:27
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

11:18 · section reference included

Separate concerns without requiring microservices

A useful boundary does not require a distributed architecture. Derks recalls building PHP applications in Laravel, with backend behavior and frontend rendering closely connected. He later used Laravel to serve APIs to a separate frontend, such as Angular or React. The important change was the interface between responsibilities, not the number of services. Agent and tool components can likewise remain in one repository while being designed separately.

Model Context Protocol, introduced by Anthropic, provides one such client–server boundary. A host such as Claude Desktop contains a client that connects to servers. Those servers expose tools and resources such as data files. The server hides backend implementation, not the tool contract: clients can discover tool names, descriptions and input schemas, then invoke the tools through the protocol.

Tool definitions, imports and backend logic can therefore live behind the MCP server, while the host and client handle the connection. Derks’s TypeScript MCP-server tutorial accompanies this part of the talk; its SDK 0.6.0 examples are historical. The architectural benefit is the durable distinction between the agent-facing client and the implementation serving its tools.

13:3913:54
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

13:39 · section reference included

A tool platform owns creation and execution

A standalone tool platform takes the separation further. Tools are defined outside the agent framework and reached through an SDK or API. The agent consumes their definitions, uses the model to select a call and passes that request to the platform for execution. The platform can also encapsulate chains of operations behind a smaller interface.

Two responsibilities make up this arrangement:

  • Creation: turn APIs or databases into tools, typically through code or a CLI.
  • Execution and surfacing: host the implementation and expose it to frameworks such as LangChain or CrewAI through SDKs.

Repeated sequences are candidates for platform-side composition. To retrieve customers in the requester’s country, for example, one operation might derive the country from an IP address, then pass it to a customer query against a database or CRM. The agent need not reconstruct that same sequence every time.

The boundary is also a place to handle authorization, authentication and errors. A CRM and a database may need different credentials, each passed to a different underlying system. Keeping those concerns outside the agent framework prevents every agent integration from becoming another implementation of the same credential-handling logic.

Derks says building tools usually takes him the longest. Preserving that investment makes framework changes less expensive: the same tool implementation can be surfaced to LangChain, LangGraph, CrewAI or AutoGen. He names Composio, Toolhouse, Arcade AI and Wildcard among the platform examples at the time, while disclosing that he is building a tool platform at IBM himself.

16:1916:30
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

16:19 · section reference included

Keep embedded orchestration and move tool execution

The integration example combines an IBM watsonx model, a LangGraph ReAct agent and WX Flows, IBM’s watsonx.ai Flows Engine. A LangChain-specific SDK connects the agent to tools defined on the platform. For the remote setup, Derks supplies an endpoint and API key, then retrieves the tools. He also describes a local alternative that brings in functions or interfaces directly.

The agent still receives a model and tools, but those tools now provide a route to remote execution rather than containing all the implementation locally. Loop ownership and tool hosting are separate architectural choices. Embedded orchestration can remain inside the agent while the platform executes the requested operations.

The agent continues to manage subsequent calls; moving the tools does not eliminate its loop. What changes is the coupling: LangGraph can be replaced, or its ReAct agent can give way to another pattern or a graph-based workflow, without moving the tool implementation along with it.

19:4719:56
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

19:47 · section reference included

Replace a growing catalog with schema-guided queries

Even reusable tools can proliferate. A CRM has customers, country filters, orders, contracts and employee details; other databases add products and payments. Creating a separate tool for every entity and variation quickly makes selection more complicated. Derks informally contrasts roughly ten tools, which may work well, with a hundred, which may confuse an agent; he supplies no model versions or evaluation results for that comparison. Routers in a framework or platform are one response to a large catalog.

A dynamic tool offers another response: accept a query instead of only a fixed set of task-specific arguments. Rather than selecting a customer tool and supplying a Europe filter, the model generates GraphQL for an API. The tool instruction asks for valid GraphQL; the query becomes the tool’s input.

To make that possible, supply the GraphQL schema. It describes available operations and the types of data they return. For the Europe-customer example, a minimal teaching schema and a proposed query could look like this:

graphql

type Customer {
  id: ID!
  name: String!
  region: String!
}

type Query {
  customers(region: String!): [Customer!]!
}

graphql

query CustomersInEurope {
  customers(region: "Europe") {
    id
    name
  }
}

The schema gives the model the operation name, required argument and selectable result fields. The generated query is still a proposed tool input; obtaining customer records requires the tool to execute it against the API.

Derks reports promising experiments with Llama, OpenAI models and Claude when the schema is supplied and queries stay simple. His practical guidance is to avoid custom scalars that confused models and keep nesting shallow: one level may work, while five levels can become confusing. These are observations from his tests, not measured reliability thresholds. He also reports that models understand GraphQL fragments, so the approach can use more of the language than a single hard-coded query template.

Dynamic tools can reuse existing APIs, databases and business logic instead of recreating that logic across many downstream tool definitions. The price of that flexibility is a larger space of possible mistakes. A model may generate good GraphQL on one attempt, then hallucinate fields or produce malformed syntax on another. Reducing the number of tool definitions does not remove the need to engineer reliable execution; it changes the contract that must be made reliable.

Static vs dynamic tools slide with a GraphQL logo and code example, listing compatibility with existing APIs and databases, less downstream implementation, more flexibility and possible LLM hallucinations.Open full source frame
Dynamic tools offer flexibility alongside the risk of LLM hallucinations.

That is where the talk ends: tools deserve as much attention as the agents that call them. Whether the interface is a fixed function, an MCP server, a hosted platform or a generated query, it is the tool implementation that connects the agent’s decision to useful work.

21:2321:37
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

21:23 · section reference included

Resources

From the talk

Transcript download
Read the transcript and explore slides

Loading transcript and slides…