What This Example Shows
- All four edge syntaxes the Graph Workflow endpoint actually parses
- Side-by-side examples where each format produces the same three-agent DAG
- How to express multi-target (fan-out) edges and conditional gating
- A summary table for picking the right format for the job
- One end-to-end runnable workflow that mixes formats in a single
edgesarray
Why This Matters
Most teams adopt Graph Workflow with one edge format in mind — usually the dict form{"source": "A", "target": "B"} — then run into friction when their DAG grows or when ops needs to tag specific edges. The API accepts four interchangeable formats: two dict forms and two list forms, with metadata available on either. Pick the right one for the job and your edges file stays scannable; pick the wrong one and your diff reviewers cry. This reference walks every format end to end against the same target DAG so you can see the trade-offs in one place, and shows how to compose multi-target fan-outs and prompt-level conditional gating without inventing a syntax the API doesn’t actually support.
Step 1: Setup
Install dependencies and load your API key.Step 2: Define the Shared Agent Pool
Every example below reuses the same three-agent pool so only the edges change between formats.Step 3: Format 1 — Dict Form
The canonical and most common format. Each edge is a dictionary with explicitsource and target keys. Verbose but extremely readable in code reviews — most production codebases standardize on this.
Step 4: Format 2 — Dict with Metadata
The dict form plus an optionalmetadata field — a free-form dictionary you can attach to any edge for routing hints, priority labels, telemetry tags, retry policies, or downstream business rules. The metadata travels with the edge through the compiler.
Metadata keys are unconstrained — use whatever your ops or audit tooling expects. Common patterns:
priority, retry_on_failure, audit_tag, data_type, timeout, cost_center. See Tagging Graph Workflow Edges with Metadata for the full production playbook.Step 5: Format 3 — Two-Element List
The most terse format the API accepts. Each edge is a two-element list (or tuple) of[source, target]. Best for short pipelines and quick scripts where you want the graph to read like a list of arrows.
Tuples work identically to lists in Python —
("Agent1", "Agent2") and ["Agent1", "Agent2"] both serialize to the same JSON array and the API treats them the same. Pick the one your codebase already uses for graph edges elsewhere.Step 6: Format 4 — Three-Element List with Metadata
The list form’s metadata variant. Add a third element holding the metadata dictionary. Same expressive power as the dict-with-metadata form, fewer characters per edge — at the cost of positional readability.Step 7: Multi-Target (Fan-Out) Edges
There is no dedicated multi-target syntax in the API — you express a fan-out by writing one edge per downstream target, all sharing the same source. The compiler builds the parallel branches and runs them concurrently. This is the same expressive power as a hypothetical"A -> [B, C]" shorthand, just stated explicitly.
source produce an N-way fan-out, and N edges with the same target produce an N-way fan-in. The full DAG is just a list of pairwise edges; structure emerges from the edge set.
Step 8: Conditional Edges via Prompt-Level Gating
The Graph Workflow endpoint does not expose a schema-levelcondition field on edges — every declared edge fires when its upstream node completes. To implement a conditional path, encode the gate in the downstream node’s prompt:
HumanEscalation node runs every time, but produces a SKIPPED no-op when the upstream emits PASS. Downstream consumers (or a final synthesis node) check for SKIPPED and ignore the branch. See Graph Workflows for Production Pipelines for the full SKIP-gating pattern in a real DAG.
Step 9: Mix Formats in One Workflow
The compiler accepts heterogeneous edges in the sameedges array. Sketch the trunk of the graph with the list form and switch to dict-with-metadata for the edges ops actually cares about.
Step 10: Read the Per-Node Output
Regardless of which edge format you submit, the response shape is identical. Outputs are keyed byagent_name.
Choosing the Right Format
| Format | Best for | Pros | Cons |
|---|---|---|---|
Dict form {"source": ..., "target": ...} | Most production codebases | Explicit, lints cleanly, easy to refactor | Verbose for large graphs |
| Dict with metadata | Edges that need routing hints, audit labels, or retry policy | Carries ops and business context with the edge | Most verbose; only worth it when you consume the metadata |
Two-element list [source, target] | Sketches, quick scripts, dense edge lists | Fewest characters; reads like an arrow | No metadata; positional — typo-prone |
Three-element list [source, target, metadata] | Dense edge lists where most edges need a tag | Compact metadata variant | Positional; less self-documenting than dict form |
| Multi-target fan-out | One upstream feeding many parallel downstreams | Pure composition — no new syntax | Verbose for very wide fan-outs |
| Conditional gating | Skipping branches based on upstream signal | No new syntax; pure prompt engineering | Downstream node still consumes tokens to emit SKIPPED |
A common production convention: use the two-element list inside
if __name__ == "__main__" smoke tests, the dict form in committed pipeline modules, and dict-with-metadata only on edges that participate in audit, retry, or routing logic.Common Pitfalls
400 error: `Invalid edge format`
400 error: `Invalid edge format`
The API expects each edge to be a dict, an
EdgeSpec, or a list/tuple of length 2+. Strings like "Agent1 -> Agent2" are not parsed and will fail validation. If you want a terse syntax, use the two-element list.400 error: `source node '...' does not exist`
400 error: `source node '...' does not exist`
Every edge’s
source and target must match an agent_name in the agents array exactly. Watch for whitespace, casing, and trailing punctuation — the comparison is exact.A downstream node never runs
A downstream node never runs
Check that the downstream node appears as the
target of at least one edge whose source actually executes. A node with no incoming edge and no entry in entry_points will never fire.Next Steps
- Tagging Graph Workflow Edges with Metadata — production patterns for routing hints, telemetry tags, and audit labels
- Graph Workflows for Production Pipelines — a fan-out/fan-in SDR enrichment DAG using the dict form end to end
- Graph Workflow Example — additional DAG shapes including localization and code review