Skip to content
Merged
130 changes: 129 additions & 1 deletion docs/graphs/data-handling.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Data handling for agent workflows

<div class="language-support-tag">
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v2.0.0</span><span class="lst-go">Go v2.0.0</span>
<span class="lst-supported">Supported in ADK</span><span class="lst-python">Python v2.0.0</span><span class="lst-typescript">TypeScript v2.0.0</span><span class="lst-go">Go v2.0.0</span>
</div>

Structuring and managing data between agents and graph-based nodes is critical
Expand All @@ -28,6 +28,31 @@ receives it as its typed input.
- **`state`**: Data automatically persisted across nodes via ***Events***
throughout an ADK session.

=== "TypeScript"

In ADK TypeScript v2.0.0, nodes exchange data through events. The key
fields for node data handling are:

- **`output`**: the value passed to the next node. Return a value
directly and ADK wraps it in an event, or set the field explicitly
with `createEvent({output})`.
- **`content`**: a message for the user. The runtime renders this
field, but the graph does not pass it to the next node.
- **`route`**: the routing keys that select which conditional edge to
follow.

Session state is separate from the event. A node reads and writes state
through `ctx.state`, and the accumulated delta is attached to that
node's events. State keys can carry a prefix that controls their
lifetime and scope:

| Prefix | Scope |
|---|---|
| `app:` | Shared across all users and sessions for the app |
| `user:` | Tied to the user, shared across their sessions |
| `temp:` | Discarded after the current invocation ends |
| *(none)* | Persists for the lifetime of the session |

=== "Go"

In ADK Go v2.0.0, the data-passing mechanism depends on which agent style
Expand Down Expand Up @@ -89,6 +114,23 @@ Each step in a workflow produces output for its successor.
***return*** or ***yield*** command without a parameter passes a `None` value
to the next node.

=== "TypeScript"

There are three equivalent ways to produce a node's output: return a
value directly, return `createEvent({output})`, or yield events from an
async generator to stream progress alongside the result.

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/node_output.ts:node-output"
```

!!! warning "Caution: emit `output` from one event per execution"

A node can yield any number of events carrying `output`, and ADK
does not raise an error in this case. Each event overwrites the
previous one, and the successor node receives only the final value.
Use `content` for progress messages instead.

=== "Go"

**workflow package**: a `FunctionNode` simply returns a typed Go value.
Expand Down Expand Up @@ -131,6 +173,18 @@ Each step in a workflow produces output for its successor.
one ***yield*** in a node, having two or more ***yield*** commands with
an ***Event.output*** results in a runtime error.

=== "TypeScript"

The `output` field is not limited to text. Any serializable value is
passed to the next node, which receives it as a typed object, with no
JSON parsing or state reads required. Attaching an `outputSchema` to the
producing node, or an `inputSchema` to the consuming node, makes the
contract explicit and validates it at runtime:

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/structured_output.ts:structured-output"
```

=== "Go"

**workflow package**: a `FunctionNode` can return any JSON-serializable
Expand Down Expand Up @@ -159,6 +213,16 @@ Each step in a workflow produces output for its successor.
return Event(route="BUG")
```

=== "TypeScript"

The `route` value is independent of `output`, so one event can both
select a branch and forward a payload to it. The `DEFAULT_ROUTE` setting
catches any value that no other branch matched:

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/routing_output.ts:routing-output"
```

=== "Go"

**workflow package**: an emitting `FunctionNode` constructs a
Expand All @@ -184,6 +248,17 @@ Each step in a workflow produces output for its successor.
yield Event(message="Beginning research process...")
```

=== "TypeScript"

A message for the user is the event's `content` field. The runtime
renders `content`, but the graph does not pass it to the next node. Use
`content` for the user and `output` for the next node. A node can emit
both by sending two events, where only one carries `output`:

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/user_message.ts:user-message"
```

=== "Go"

**workflow package**: to emit a user-visible message without advancing
Expand Down Expand Up @@ -239,6 +314,24 @@ inside tools and callbacks regardless of which agent style you use.
such as database Tools, to persist large data resources during the life
cycle of a Workflow.

=== "TypeScript"

Write state through `ctx.state` rather than returning it. A write is
visible to every later node in the same run, and is committed with the
writing node's events:

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/session_state.ts:session-state"
```

!!! warning "Caution: `state` data limitations"

Session state is a lightweight key-value store. Do not use it to
move large payloads between nodes; use artifacts or a database tool
instead. When only the next node needs a value, pass it along the
edge as node `output`. Use state when a value must outlive the run,
or be read by a tool, a callback, or `{key}` instruction templating.

=== "Go"

State is written with `ctx.Session().State().Set(key, value)` and read
Expand Down Expand Up @@ -306,6 +399,24 @@ accepted and produced by any agent node.
)
```

=== "TypeScript"

Schemas are Zod objects or a genai `Schema`. The location of the schema
determines its effect:

- The `LlmAgent.outputSchema` option requires the model to answer in
that shape.
- The `LlmAgent.inputSchema` option applies only when the agent is
exposed as a tool. Inside a graph, set the schema that validates a
node's input on the node itself, using `node(agent, {inputSchema})`.

Agents in a graph must run in `single_turn` mode, which is the default,
or `task` mode.

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/schemas.ts:schemas"
```

=== "Go"

**workflow package**: use `workflow.NewAgentNodeTyped[Input, Output]` to
Expand Down Expand Up @@ -368,6 +479,23 @@ accepted and produced by any agent node.
)
```

=== "TypeScript"

Two data-selection forms are available inside an agent instruction:

- The `{Class.field}` form reads a field from this node's input.
- The `<Class.field from source_node>` form reads a field from a named
predecessor's output. Use this form when several upstream nodes
share a field name.

Both forms are distinct from `{state_key}`, which reads session state.
The `Class.` prefix is documentation only; resolution uses the field
name after the dot.

```typescript
--8<-- "examples/typescript/snippets/graphs/data-handling/structured_access.ts:structured-access"
```

=== "Go"

In ADK Go v2.0.0, a `FunctionNode` returns a typed struct and the
Expand Down
Loading
Loading