Skip to content

Chains Capability Specification

Capability Identity

PropertyValue
EnumA2ECapability.CHAINS
String"chains"
Plugin TypeChainPlugin
Plugin Priority10
Namespacechain/*
Message Count3

Overview

The chains capability provides multi-step skill/tool pipeline execution declared as a Directed Acyclic Graph (DAG). The host executes the chain, passing outputs from upstream nodes as inputs to downstream nodes. Chains enable complex workflow orchestration with parallel execution, conditional branching, and fan-out patterns.

Chain node types:

  • skill — Invoke a skill by name
  • tool — Call a native tool
  • proc — Spawn a process (via proc capability)
  • branch — Conditional fork (if/else on a JMESPath expression)
  • map — Fan-out: apply one node to a list of items in parallel

Protocol Flow

Message Types (3)

chain/req — ChainRequest

Agent → Host. Execute a skill/tool chain.

FieldTypeRequiredDefaultDescription
typestrYes"chain/req"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
session_idstrYes""Session from HandshakeResponse
chain_idstrNoauto hex[:8]Chain identifier
nodeslist[dict]Yes[]List of ChainNode dicts (must form valid DAG)
entry_nodestrYes""node_id of the first node to execute
initial_inputdictNo{}Seed input available to all nodes as $.input
correlation_idstrNo""Ties to agent turn/trajectory
streamingboolNoTrueEmit ChainEvent messages during execution
timeoutintNo300Chain wall-clock limit (seconds)

chain/event — ChainEvent

Host → Agent. Progress update during chain execution. Extends A2EEvent.

FieldTypeRequiredDefaultDescription
typestrYes"chain/event"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
req_idstrYes""Correlates to ChainRequest ID
node_idstrYes""Which node the event pertains to
phasestrYes"start"Execution phase (see Phases below)
outputAnyNoNoneNode output (populated when phase="done")
errorstrNo""Error message (populated when phase="error")
seqintYes0Monotonic sequence number

Phase values:

PhaseDescription
startNode execution has begun
doneNode completed successfully
skipNode was skipped (branch condition)
errorNode execution failed

chain/resp — ChainResponse

Host → Agent. Final result of the full chain.

FieldTypeRequiredDefaultDescription
typestrYes"chain/resp"Message type identifier
idstrYesauto UUIDMessage UUID
versionstrYes"1.0"Protocol version
tsfloatYesautoUnix epoch timestamp
req_idstrYes""Echoes request ID
chain_idstrYes""Chain identifier
successboolYesFalseWhether all nodes completed without error
outputsdictYes{}Map of node_id → output for all completed nodes
final_outputAnyNoNoneOutput of the terminal node(s)
duration_msintYes0Total chain execution time
nodes_runintYes0Number of nodes executed
errordictNoNoneError details if chain failed

Data Models

ChainNode

FieldTypeRequiredDefaultDescription
node_idstrYesUnique node identifier within the chain
kindstrYesNode type: skill, tool, branch, map
namestrNo""Skill name or tool name to invoke
inputdictNo{}Static input values
input_mapdictNo{}Input templates: keys are input field names, values are JMESPath expressions evaluated against chain context
conditionstrNo""JMESPath boolean expression (branch nodes)
true_nodestrNo""node_id to run if condition is True (branch)
false_nodestrNo""node_id to run if condition is False (branch)
items_pathstrNo""JMESPath → list to iterate (map nodes)
map_nodestrNo""node_id to apply to each item (map nodes)
next_nodestrNo""Default successor node_id
on_errorstrNo"abort"Error handling: abort, skip, or a node_id

Error Codes — ChainErrorCode

CodeEnum ValueDescriptionRetryable
chain_cycleCHAIN_CYCLEDAG contains a cycleNo
chain_node_errorCHAIN_NODE_ERRORA node execution failedDepends

Execution Model

Dependency Resolution

The chain executor uses a thread-based scheduler:

  1. Build node index: Map node_id → ChainNode
  2. Track state: completed, running, failed sets
  3. Evaluate readiness: A node can run when all its dependencies (nodes that appear in its input_map) are in completed
  4. Resolve inputs: Merge static input with resolved input_map values
  5. Parallel execution: Ready nodes spawn on daemon threads
  6. Poll loop: Check for newly-ready nodes every 10ms

Node Execution Types

KindExecution
toolCalls host.tool_registry.get(name).runner(input, callback)
procSpawns process via host.get_plugin("proc"), blocks until completion
skillCalls skill execution (requires skill capability)

Terminal Node Detection

A node is "terminal" if no other node lists it as a dependency. The last terminal node's output becomes final_output.

Wire Examples

Simple Linear Chain

json
{"type":"chain/req","id":"c1","version":"1.0","ts":1716123456.789,"session_id":"s1","chain_id":"abc123","nodes":[{"node_id":"read","kind":"tool","name":"read_file","input":{"path":"/data/input.txt"},"input_map":{},"next_node":"summarize","on_error":"abort"},{"node_id":"summarize","kind":"skill","name":"text_summarizer","input":{},"input_map":{"text":"read.output"},"on_error":"abort"}],"entry_node":"read","initial_input":{},"streaming":true,"timeout":300}

Branch Node

json
{"node_id":"check","kind":"branch","condition":"length(output.items) > `0`","true_node":"process","false_node":"skip_log"}

Map Node (Fan-out)

json
{"node_id":"batch","kind":"map","items_path":"input.files","map_node":"process_file"}

Security Considerations

  1. Cycle detection: Host must validate DAG before execution (reject cycles)
  2. Node count limits: Host should enforce maximum nodes per chain
  3. Timeout enforcement: Chain-level timeout prevents infinite execution
  4. Error propagation: on_error policy determines how node failures affect downstream nodes
  5. Thread isolation: Node execution runs in daemon threads; chain timeout can kill stuck threads

A2E Protocol v1.0 — Released under the MIT License.