Skip to main content
Version: 2.0

Call other tools from lambda tools

A lambda tool can call other tools — searches, sub-agents, web fetches, even other lambdas — from its own Python code. It declares tool_configurations (the same configuration shape agents use) and calls each one as a plain function; each call runs server-side and returns its result to the lambda. This lets a lambda reach data outside the sandbox — HTTP APIs, corpora, artifacts — without itself getting network access.

This unlocks lambdas that:

  • Call a guarded REST API through a pinned web_get configuration, with the bearer token pulled from agent secrets — the credential never appears in your code, the sandbox, or session events.
  • Read files the user uploaded through the artifact_read tool, then parse, validate, or reshape them with your own logic.
  • Search your corpora and post-process the hits before the agent sees them.
  • Chain other lambdas, splitting a workflow into small, testable functions.

The composed tools stay private to the lambda: they never appear on the tool surface of an agent that uses the lambda, and their calls produce no session events. To the agent, your lambda is still one tool with one input and one output.

The tool module

When a lambda declares tool_configurations, its code gets a built-in tool module — no import, no setup:

CALLING A CONFIGURED TOOL FROM LAMBDA CODE

Code example with python syntax.
1
  • tool.<name>(param=value, ...) calls the configuration named <name> with keyword arguments and returns its result as a dict.
  • tool.list() returns every callable tool's name, description, and input schema.
  • Failures raise tool.ToolError with the platform's error message — catch it if your lambda can degrade gracefully.

Run composed calls in parallel

When calls are independent, don't run them one at a time. Every callable also carries tool.<name>.submit(param=value, ...): it starts the call and returns a handle immediately; handle.result() waits for that call's result — or re-raises that call's tool.ToolError, without affecting its siblings. submit is a capability of the sandbox's tool module; the API reference for tool_configurations describes only the synchronous surface (tool.<name>(...), tool.list(), tool.ToolError).

PARALLEL FAN-OUT WITH PER-CALL ERROR ISOLATION

Code example with python syntax.
1

Things to know:

  • Submit everything before collecting anything. Calling submit then immediately result in the same loop iteration runs the calls sequentially again — the pattern above starts all calls first, then collects.
  • A limited number of calls run concurrently — currently 8, a platform behavior rather than an API guarantee. Submits beyond the limit queue and start as slots free up — a wider fan-out just takes proportionally longer. Concurrent executions of the same lambda in one session share a per-session in-flight limit, and overflowing it raises tool.ToolError from handle.result() — catch it per handle, as the example does.
  • Set max_execution_time_seconds explicitly — do not rely on a default. A lambda that declares tool_configurations and omits execution_configuration entirely resolves to 300 seconds, whereas any other lambda resolves to 30. But supplying execution_configuration without this field stores 30, so most lambdas — including every one saved from the console — run at 30 unless you set it. Set it to the budget your fan-out actually needs.
  • Both timeout knobs accept up to 21600 seconds. max_execution_time_seconds in the agent's tool_configurations entry for the lambda takes precedence over execution_configuration when both are set, so use it to give one agent a longer budget than the lambda's own default.

Example: parallel sub-agent fan-out

The pattern above is how you build a deep-research-style orchestrator: the model makes one call to a fan-out lambda, and the lambda parallelizes the delegation deterministically instead of depending on the model to emit many tool calls at once.

CREATE A RESEARCH FAN-OUT LAMBDA

Code example with curl syntax.
1

The hosting agent then exposes it with a timeout sized for the fan-out:

AGENT TOOL CONFIGURATION

Code example with json syntax.
1
Parallel sub-agents need one session per call

Keep session_mode: ephemeral (the default) on a sub-agent configuration you fan out to. persistent mode reuses one session per (parent session, tool configuration) pair, so parallel submits through the same configuration are funneled into a single session and return overlapping answers instead of one answer per question. The same applies to session_scoped and agent_scoped (and the deprecated llm_controlled alias) if you pass the same session_key to concurrent submits — omit it and each call gets its own session.

Note

Composed calls produce no session events, so the parent agent's clients see no sub-agent progress while the fan-out runs — results arrive when the lambda returns. Keep per-question scope tight enough that the whole fan-out fits the configured timeout.

Sub-agent chains are not depth-limited by the platform: a delegate that itself fans out multiplies the work at every level. Keep the delegate graph acyclic and size max_execution_time_seconds for the whole tree.

Variant: specialist branches

Instead of fanning one question list over a single sub-agent, give the lambda several specialist sub-agents and send each a differently-framed prompt. The hosting agent still makes one call; each branch fails independently and the survivors' answers come back regardless:

PARALLEL DEEP RESEARCH ACROSS SPECIALIST SUB-AGENTS

Code example with python syntax.
1

Each specialist is its own tool_configurations entry — same shape as before, one per branch, every one ephemeral:

ONE SUB_AGENT ENTRY PER SPECIALIST

Code example with json syntax.
1

Example: a ticket summarizer with a secret-guarded API

This lambda wraps a ticketing API behind a single summarize_ticket tool. The API needs a bearer token, but the token lives in the agent's secrets — the lambda code only ever sees the response.

1. Create the lambda with its tool configuration

CREATE A COMPOSABLE LAMBDA TOOL

Code example with curl syntax.
1

Everything in argument_override is decided by you, not by the lambda: the code chooses only url_suffix, while the base URL comes from the hosting agent's metadata and the token from its secrets, both resolved at execution time.

2. Test it without an agent

POST /v2/tools/test runs lambda code before you create anything. The test_context field stands in for the hosting agent and session, so $refs resolve exactly as they will in production. For a test that runs longer than a few minutes, set stream_response: true and accept text/event-stream (budgets above 300 seconds require it): the platform emits heartbeat events to keep the connection alive while the function runs, and finishes with one result event carrying the same object the non-streaming response returns.

TEST THE LAMBDA AND ITS TOOL CALLS

Code example with curl syntax.
1

A $ref that names a key missing from test_context fails the test with a resolution error — you find configuration mistakes here, not in production.

3. Attach the lambda to an agent

The agent references the lambda like any other tool. It sees one tool, summarize_ticket, with one parameter:

AGENT TOOL CONFIGURATION

Code example with json syntax.
1

At runtime the lambda's internal fetch_ticket resolves its $refs against this agent's metadata and secrets. Different agents can host the same lambda with different endpoints and credentials — the code never changes.

Reference a reusable configuration instead of inlining

The examples above define each composed tool inline. You can instead point an entry at a reusable tool configuration — one managed independently through the /v2/tool_configurations API and shared across agents and lambdas — by giving it type: reference and the configuration's key:

A LAMBDA THAT REFERENCES A SHARED CONFIGURATION

Code example with json syntax.
1
  • The map key (fetch_ticket) is still the name your code calls — tool.fetch_ticket(...). It is independent of the referenced configuration's own name.
  • tool_configuration_key is the key of the reusable configuration to resolve.
  • Everything the shared configuration defines — its tool, its argument_override, and any $refs inside it — still resolves against the hosting agent and session at execution time, exactly as an inline entry would. Update the shared configuration once and every lambda that references it picks up the change on its next run.
  • A reference to a key that does not exist is rejected when the lambda is created (or when you call POST /v2/tools/test), naming the unresolvable key.

Inline and reference entries can be mixed freely in the same tool_configurations map.

What $ref resolves against

$ref values inside a composed tool's argument_override resolve from the hosting agent and session at execution time:

ReferenceResolves to
agent.metadata.<key>The hosting agent's metadata
agent.secrets.<key>The hosting agent's secrets, masked in session events
session.metadata.<key>The current session's metadata

References to other tools' outputs (tools.*) are not allowed on a lambda's own configurations — they would couple the lambda to the configuration names of whatever agent hosts it.

Rules and limits

Constraints
  • At most 20 tool configurations per lambda.
  • sandbox_exec and invoke_skill cannot be composed into a lambda.
  • A composed tool may itself be a lambda with its own tool_configurations; nesting has no fixed depth limit. A session wires at most 1024 lambda scopes; lambdas past that cap run without the tool and artifacts bridges.
  • A lambda that appears again on its own composition path is wired with no composed tools, so the repeated level's tool.* calls fail instead of recursing.
  • One session run shares a budget of at most 50 concurrent and 10,000 total in-code tool invocations, counted across sandbox_exec and every composed lambda. A call over the concurrency bound fails immediately rather than queueing; once the total is spent, further calls in that run fail. Both limits reset on the next run.
  • Composed calls produce no session events; their results stay inside your lambda's code unless you return them.

The same tool module is available to Python the agent runs through the built-in sandbox_exec tool — there it exposes the agent's other tools, so the model can fetch data mid-script instead of guessing values.