Skip to main content
AI agents rarely stop at a single LLM call. They search the web, query databases, send emails, and call external APIs. tp.wrapToolCall wraps any async function the same way tp.wrapOpenAI wraps completions — giving you a named span in the dashboard for every tool your agent uses, linked into the same execution tree.

How wrapToolCall works

wrapToolCall takes a tool name, an async function to execute, and the span ID of the parent span. It runs your function, records the input and output as a span, and returns both the original result and a new spanId you can use to nest further steps beneath it.
The function you pass to call can do anything: hit an HTTP endpoint, run a database query, send a message. TracePilot captures whatever it returns as the span output.

Tracing a non-destructive tool

A web search reads data without modifying anything external. Wrap it without isDestructive.
In the dashboard, the web-search span appears nested under the LLM span that triggered it, and you can inspect the query it received and the results it returned.

Tracing a destructive tool

A tool that sends an email, writes to a database, or makes a payment modifies external state. Pass isDestructive: true so anyone reviewing the trace knows this step had a real-world side effect.
Mark any tool as destructive when it modifies external state: database writes, outbound emails, payment charges, API mutations, file deletions, or webhook triggers. The badge is a signal to you and your team during incident review — not a guard against execution.

Linking tool spans to parent LLM spans

The parentSpanId parameter is what connects tool calls into the same execution tree as the LLM spans that triggered them. Every wrapOpenAI and wrapToolCall call returns a spanId. Pass that ID as parentSpanId to the next call that logically follows from it.
This builds a tree that reads like your agent’s reasoning: the LLM decided to call the tool, the tool returned data, the LLM used that data to respond.

What the dashboard shows for tool spans

Each tool span displays the tool name as its label, the arguments your function received, the return value, execution latency, and any error if the function threw. Destructive spans show a ⚠ Destructive badge in the span header.
wrapToolCall expects the call argument to be an async function (one that returns a Promise). Wrap synchronous functions in an async arrow function.
If the function passed to call throws, wrapToolCall records the error as a failed span and re-throws the original error. Add a try/catch around the call if you want to recover gracefully.
Use a short, lowercase, hyphen-separated string that describes what the tool does: web-search, send-email, get-user-record, calculate-price. Avoid generic names like tool1 or step — the name is the primary label in the span tree.