@withgateway/sdk/worlds
does two things: records the calls while the agent runs against the real vendor, and puts the
records into a world through the route you declare — your own transform, an ingest.toml
mapping, or, for a tool whose result is the vendor’s response body, the operation’s projection.
The record
One JSON object per call.tool, args and result are required; the rest is optional and
travels with the record.
gateway worlds session export ({seq, kind, tool, args, result, error, completedAt})
is accepted as it is. parseToolCallRecord(raw) tells you what the runtime will do with a
record before you send it: { record, skip, refusal } — a seed line or a failed call is a
skip with its reason, a record with no tool name or no result is a refusal.
captureToolCalls(tools, sink, options?)
Wraps a name → async function map — the shape the Vercel AI SDK’s tools and a
WorldToolkit’s impls share — and returns the same map. Each wrapped function calls the
original, returns exactly what it returned, and writes one record to the sink. An error is
thrown through untouched and recorded with error instead of result, which ingest later
skips and counts. The agent changes nothing.
options.session and options.source are stamped on every record.
ingest(world, records, options?)
world is a local directory or a platform slug (slug or slug@ref). records are tool-call
records, or any JSON objects when a mapping reads them as rows.
With neither
transform nor map, the world’s own ingest.toml applies when it has one;
else each record’s tool resolves to an [[operations]] entry of connector.toml and its
result is read at the operation’s results path and projected by its [ingest] table
(drop, explode, carry_args from the call’s args) as a captured response
is. The report says via: "operations", and its note says that this is the operation’s
projection, not a mapping. ingestToolCalls(world, records, options) is that route by name.
- A directory is written in place (
data/initial.json, the snapshot rebuilt) through the bundled schema runtime, which needs apython3≥ 3.12 on the machine. Mappings and projections run there; a transform runs where you are. - A slug is pulled to a temporary directory, the rows produced and proven there, and pushed through the chunked data batch lane as a new version.
data import would, naming the entity, index and field. A transform that fails, times out or
returns something other than {entity: [rows]} throws with its stderr.
The mapping as an object:
Redaction is optional and off by default: rows land as they were produced. Use
redact: "apply" for a world built from real users. See
Keep real data out.From traces
Instrumented agents already record every tool call as a TOOL observation. Convert those instead of intercepting:toolCallsFromObservations takes name as the tool, input as the args, output as the
result and startTime as the time, parses serialized JSON back, and sets source to
trace:<traceId>/<observationId>. Only TOOL observations convert; an ERROR-level one
becomes a failed call. With tools (the world’s operations) every other tool’s observation
lands in unknownTools instead — the filter the operations route uses. The CLI form is
gateway worlds data calls pull <out> --from traces, then gateway worlds data ingest; see
Put data in a world.
Python
The same two halves ship ingatewaysdk:
ingest_tool_calls(world, records) is the operations route by name. Both take redact
("off" by default), dry_run, mode, message and the keys.
Where to go next
- Put data in a world for
calls pull, the transform, the mapping grammar and the batch lane. - Simulations from real data for the whole funnel.
- Keep real data out for the
[redact]policy and the modes.