Status

Canonical implementation guide. Supersedes: v0.1. Companion to the n8n Implementation Guide (Layer 3) — this guide covers the Agent Runtime (Layer 4). Related specs: Synedrix OS - Agent Spec, Synedrix OS Workflow Contract Spec, Synedrix OS Outcome Spec, Synedrix OS - Agent Runtime Policy Spec, Synedrix OS Orchestration & Runtime Strategy, Synedrix OS Naming Convention Spec.

Purpose

This guide bridges the abstract Synedrix OS agent specifications to concrete LangGraph constructs, for agents that run in the Agent Runtime (Layer 4) rather than as n8n AI Agent nodes. It is the Layer-4 counterpart to the n8n Implementation Guide and implements ADR-OS-001.

A LangGraph agent is non-compliant unless it preserves the governance bridge: correlation lineage, Policy Guard reachability, HITL reachability, tool-authorization enforcement, the canonical Outcome Envelope return contract, and Langfuse tracing. A LangGraph agent that bypasses any of these is a shadow runtime.

When to use this guide

Use LangGraph (not the n8n AI Agent node) when the workflow’s execution_pattern is stateful, cyclic, or multi-agent:

execution_patternEngineThis guide?
sequential, conditional, parallel, fan-out-fan-in, pipelinen8n AI Agent nodeNo — see n8n Implementation Guide
iterative, consensus, reflect-and-revise, hierarchicalLangGraphYes

n8n still owns the trigger, the surrounding business sequence, the policy/HITL gates, and outcome persistence. LangGraph is invoked as a governed step.


1. OS concept → LangGraph construct

How each Synedrix OS concept maps onto a concrete LangGraph construct.

OS conceptLangGraph construct
Agent (agent-driven step)A compiled StateGraph (or a node within one)
Graph stateA typed State (TypedDict / Pydantic) carrying correlation_id, causation_id, task input, working state
runtime_policy.primary_modelA LangChain chat model bound into the relevant node (ChatOpenAI, ChatAnthropic, ChatOllama)
tool_permissions entry (resolved active_tool_set)LangChain tools bound to the model; the executor rejects any tool not in the passed-in active set
MCP toolLangChain MCP adapter tool, gated by mcp_tool_policy
memory_profile.working_memoryGraph state + a checkpointer (in-session)
memory_profile.canonical_memory_accessA tool node performing a Supabase SELECT
execution_pattern: iterativeConditional edge that loops back to the agent node until a convergence predicate holds
execution_pattern: reflect-and-reviseGenerator node → critic node → conditional edge (revise or exit)
execution_pattern: consensusFan-out to voter nodes → reducer node computing quorum
execution_pattern: hierarchicalSupervisor node delegating to sub-graphs
Policy gateA node calling Policy Guard (os-agt-002) before any write tool
HITL approvalA LangGraph interrupt at a checkpoint; resumed by the HITL callback
Outcome envelopeThe terminal node assembles and returns the canonical envelope
correlation_idA field in graph State, set from the invocation request, never regenerated

2. The invocation contract (n8n → LangGraph)

LangGraph is invoked by n8n over HTTP / MCP / A2A. The request and response are fixed:

Request (from n8n):

{
  "correlation_id": "corr-...",
  "causation_id": "...",
  "invocation_id": "...",
  "agent_id": "trd-agt-014",
  "execution_pattern": "consensus",
  "deployment_mode": "self-hosted-hybrid",
  "active_tool_set": ["tool:questdb-read", "tool:redis-read"],
  "input": { "...task input..." }
}
Illustrative example, not a production implementation. Review and test before use.

Response (to n8n): the canonical Outcome Envelope (see Outcome Spec), with source.type: "agent", source.id = the agent_id, and the inherited correlation_id / causation_id.

Rules:

  • The graph reads correlation_id / causation_id from the request into State and never mints new ones.
  • invocation_id is minted by the orchestration layer when it persists the invocation start row (agent_invocations) before calling the runtime. The graph reads it into State, never mints or replaces it, and uses it as the invocation key for every tool-call audit write.
  • The executor is initialized with the active_tool_set; any tool call outside it is rejected and emits agent.tool.unauthorized.
  • deployment_mode: air-gapped forces local models only — the model binding must use a local URI (Ollama/vLLM).

3. Execution pattern → graph topology

3.1 iterative

flowchart LR
  S([START]):::term --> A[agent node]:::agent --> C{convergence check}:::check
  C -- converged --> E([END]):::term
  C -. not converged .-> A

A counter in State enforces max_iterations; on exhaustion the graph routes to an escalation terminal that emits a failure outcome (mirrors the n8n MAX_ITERATIONS_EXCEEDED rule).

3.2 reflect-and-revise

flowchart LR
  S([START]):::term --> G[generator]:::agent --> K[critic]:::agent --> Q{quality >= threshold?}:::check
  Q -- yes --> E([END]):::term
  Q -- no --> X[attach critique to state]:::agent
  X -.-> G

The critique is written to State and read by the generator on the next pass (the equivalent of the n8n critique_notes injection).

3.3 consensus

flowchart LR
  S([START]):::term --> F((fan-out)):::term
  F --> V1[voter 1]:::agent
  F --> V2[voter 2]:::agent
  F --> VN[voter N]:::agent
  V1 --> R[reducer: quorum]:::agent
  V2 --> R
  VN --> R
  R --> Q{quorum met?}:::check
  Q -- yes --> E([END]):::term
  Q -- no --> X([escalate / abort]):::warn

The reducer implements the quorum function (e.g. Trading’s 4-of-7 / 5-of-8). Voter failure is isolated; the reducer assesses quorum against responders, matching the domain’s fail-closed rules.

3.4 hierarchical

flowchart LR
  S([START]):::term --> P[supervisor]:::agent
  P -- delegates --> A[sub-graph A]:::agent
  P -- delegates --> B[sub-graph B]:::agent
  A -. Outcome Envelope .-> P
  B -. Outcome Envelope .-> P
  P --> G[aggregate]:::agent --> E([END]):::term

Each sub-graph inherits the same correlation_id; sub-outcomes are nested into the parent’s execution_context.sub_workflow_outcomes.


4. Governance bridge (mandatory)

Each item maps to an OS invariant; see Orchestration & Runtime Strategy §5 and Agent Runtime Policy Spec.

ConcernImplementation in LangGraph
Lineagecorrelation_id / causation_id live in State, set from the request, returned unchanged. Every Supabase write / event carries them.
PolicyBefore any write-class tool, a policy node calls Policy Guard (os-agt-002); on block, route to a terminal that emits a blocked outcome.
HITLUse a LangGraph interrupt to checkpoint; n8n’s Wait/callback collects the decision and resumes the graph. On timeout, emit a timeout outcome.
Tool authorizationBind only the passed-in active_tool_set; reject others and emit agent.tool.unauthorized. Honor mcp_tool_policy / a2a_tool_policy.
Tool-call auditBefore dispatching any tool, insert its intent row into agent_tool_call_records under State.invocation_id and hop_index; dispatch only after it commits. When the tool returns, insert its agent_tool_call_results row. Never buffer these in Redis. See the Agent DB Schema.
OutcomesThe terminal node returns the canonical Outcome Envelope; n8n persists it (append-only) and emits os.outcome.*.
ObservabilityConfigure the LangChain/LangGraph callback to export traces to Langfuse (OpenTelemetry / native). Do not use LangSmith as a stack platform.
Audit read-onlyNever bind Audit & Lineage (os-agt-008) as a tool — it is read-only and observes, it is not invoked.

5. Naming

  • The agent keeps its canonical agent_id and human-readable name regardless of engine.
  • The n8n step that invokes a LangGraph agent uses the display-name suffix · LangGraph (Naming Convention Spec v0.4 §5.3), e.g. [TRD] L2 · Consensus · LangGraph.

6. Compliance checklist

Before declaring a LangGraph agent compliant:

  • correlation_id / causation_id are inherited from the request and returned unchanged.
  • invocation_id is read from the request into State and used for every tool-call audit write; the graph never mints one.
  • Every tool call has an intent row committed before dispatch and a result row after it returns.
  • The graph is initialized with the passed-in active_tool_set; unauthorized tool calls are rejected with agent.tool.unauthorized.
  • Every write-class tool call passes Policy Guard when required.
  • HITL is reachable via an interrupt + callback; timeouts produce a timeout outcome.
  • The terminal node returns the canonical Outcome Envelope; n8n persists it and emits os.outcome.*.
  • Traces export to Langfuse; no LangSmith dependency.
  • deployment_mode: air-gapped agents use local model URIs only.
  • Audit & Lineage (os-agt-008) is not bound as a tool.

Versioning


Core specs (what this guide implements)

Orchestration and runtime

Teaching material

  • Synedrix OS Academy — Layer 4 teaching material. Section 04 covers the runtime internals underneath this guide, chapter 06.3 covers the invocation contract, and chapter 02.4 covers tool-authorization enforcement in the conditional edge. Teaching material, not normative: where a chapter disagrees with this guide, this guide wins.

Synedrix OS · June 2026