This page explains how an “agent” and a “workflow” in the abstract specs (Agent Spec, Workflow Contract Spec) become concrete execution — and specifically why Synedrix OS splits that execution across two platforms rather than one.

Why there are two execution engines

Historically every agent-driven step ran as an n8n AI Agent node (@n8n/n8n-nodes-langchain.agent), which is itself a low-code wrapper over LangChain. This entangled two different concerns in one visual-graph tool: orchestration (sequencing, gates, retries — inherently acyclic/deterministic) and agent reasoning (stateful, cyclic, multi-agent cognition). Cyclic patterns like iterative and consensus had to be hand-simulated in n8n Code nodes with manually managed iteration counters.

ADR-OS-001 resolved this: adopt LangGraph as a dedicated Agent Runtime (Layer 4), built on LangChain, and reposition n8n to pure orchestration (Layer 3 only). The ADR explicitly rejected LangSmith (proprietary SaaS — violates Principle 11 open-by-default and the air-gapped deployment mode — and duplicates Langfuse, which is retained as the Layer 10 LLM-engineering platform). Full rationale: docs/os/synedrix-os-orchestration-runtime-strategy-v0.1.md.

The n8n ↔ LangGraph boundary

LangGraph is invoked as a governed step inside an n8n workflow — the general rule, via HTTP (internal calls), MCP (when consumed as a tool/context server), or A2A (cross-platform delegation at the platform edge) — with the sole bounded exception of os-agt-009 (General Chat Agent): a standalone LangGraph service invoked directly by the synedrix.io website via Vercel that bypasses the n8n governance bridge, compliant only while its decision_scope remains recommend with no write-class tool bound:

sequenceDiagram
    participant N as n8n Workflow
    participant P as Policy Pre-Gate
    participant L as LangGraph Runtime
    participant O as Outcome Persister

    N->>N: trigger → input validation → correlation-id init
    N->>P: deterministic glue, policy pre-gate
    N->>L: invoke via HTTP / MCP / A2A
    Note over N,L: carries correlation_id, causation_id,<br/>invocation_id, task input,<br/>active_tool_set, deployment_mode
    L->>L: stateful agent graph executes<br/>(in-graph policy/HITL calls)
    L->>N: returns the canonical Outcome Envelope
    N->>O: outcome persist (append-only)
    N->>N: emit os.outcome.* → continue / gate / escalate

The n8n↔LangGraph boundary flow — the governed invocation carries lineage IDs and an invocation_id, and returns a canonical Outcome Envelope; os-agt-009 is the sole bounded exception.

Two-level runtime-engine resolution

Level 1 — Workflow host (pattern decides)

The routing table in Orchestration & Runtime Strategy §4 selects n8n or LangGraph as the workflow host from execution_pattern:

execution_patternWorkflow hostRationale
sequential, conditional, parallel, fan-out-fan-in, pipelinen8nLinear/branching, no shared evolving state
iterative, consensus, reflect-and-revise, hierarchicalLangGraphCyclic reasoning, multi-agent consensus, checkpointed recovery, hierarchical sub-workflows

Level 2 — Agent engine (agent decides)

Each participating agent’s runtime_engine field selects the agent engine its invocations run on: n8n-aiagent or langgraph. The compatibility matrix says which combinations are legal:

Workflow hostParticipating agent’s runtime_engineResult
n8nn8n-aiagentLegal: an n8n AI Agent node
n8nlanggraphLegal: an n8n step that invokes the LangGraph runtime through the governance bridge, passing active_tool_set
LangGraphlanggraphLegal: a node in the shared graph
LangGraphn8n-aiagentIllegal. A participant in shared, evolving state must live in the graph

The one illegal pair is the original rule restated for the host it was always meant to protect: a cyclic workflow cannot run on n8n.

Services and participants

A participant is an agent named in the workflow’s agent roles. A service is a control agent reached through the governance bridge — in practice os-agt-002 (Policy Guard) and os-agt-004 (HITL Gateway). The compatibility matrix applies to participants only. For services the check is different: the bridge must be able to reach them from the workflow host. This is the existing “Policy Guard and HITL reachability” requirement of the governance bridge, applied to the host. The engine rule exempts these services entirely (D3 of ADR-025).

Agent-internal loops must be bounded

Under ADR-025, a loop inside one agent invocation — such as a ReAct tool loop — is a property of the agent, not a workflow pattern. Before, iterative on the workflow warned a reader that something unbounded might run. Now the workflow reads as a straight line; the warning moves to the agent.

Reclassifying the POCs

Under ADR-025, WF-OS-POC-001 (SearXNG research agent) is a sequential workflow hosted by n8n whose agent poc-agt-001 has runtime_engine: langgraph and a declared loop bound (max_iterations: 5). It is the first conformance case for D2 and D4 of ADR-025. The POC contracts WF-OS-POC-002 (Semantica GraphRAG retrieval) and WF-OS-POC-003 (EverOS memory recall and distillation) follow the same pattern. Full contracts: docs/os/synedrix-os-poc-n8n-langgraph-workflow-v0.2.md.

Workflow host and agent engine in manifests

ADR-024 (executable manifests) makes schema-validated YAML manifests the authoritative source for OS definitions, and ADR-026 (manifest compile, seal, release) adds the compile pipeline that turns validated manifests into runtime artifacts. These decisions depend on ADR-025’s two-level resolution.

The compile pipeline

manifest (validated, ADR-024)
  -> intermediate form (host-neutral graph + resolved references + injected governance)
  -> emitter: n8n-as-code TypeScript   (workflow host: n8n)
  -> emitter: LangGraph graph builder  (workflow host: LangGraph)
  -> emitter: n8n JSON                 (fallback only)
Illustrative example, not a production implementation. Review and test before use.

Validation and compilation never deploy. Deployment is a step of governed activation, after sealing. The compiler applies the shared governance rule set of ADR-024 to the intermediate form: a call to os-agt-002 before every side-effecting step (a block decision is final and no generated path retries or routes around it), approvals compiled by approval type to os-agt-002, os-agt-004 or both, only the active_tool_set passed to an agent step, and correlation/causation IDs carried through.

Governance is additive

Compile-time governance is an addition to — not a replacement for — the runtime checks of the governance bridge. The runtime checks remain mandatory for every workflow. A scheduled drift check detects when a deployed workflow differs from what was compiled. Activation verifies that each artifact’s hash equals the sealed hash and that the release signature is valid. See docs/os/synedrix-os-manifest-spec-v0.1.md and ADR-OS-026 for full detail.

Platform releases carry lineage

A sealed platform release records the manifests with their full transitive dependency closure (id, version, sha256), the compiled artifacts and their hashes, the compiler identity, the source commits, and the schema versions. Invocation records, outcomes, and events carry the executing manifest reference (id@version), the release hash, and the deployment record ID, so any execution can be traced to the exact release and to the bindings and materialized artifact it ran with. A production release contains only canonical manifests.

Agent anatomy

Full spec: docs/os/synedrix-os-agent-spec-v0.3.md. An agent is a contract-centric, not prompt-centric, artifact — the durable value is explicit authority, workflow contracts, policy bindings, and observability, not prompt wording. Anatomy sub-objects: Identity, Purpose, Authority, Prompt policy, Contracts (input/output/events/side-effects), Tool permissions, Memory profile, Task surface, Workflow roles, Interoperability (MCP/A2A), Runtime policy (includes the runtime_engine field: n8n-aiagent | langgraph and an optional reasoning_loop block), Policy bindings, Observability.

The canonical Mission → Goal → Task → Action hierarchy: Mission is why the agent exists (agent-owned, static, agent_version); Goal is a bounded desired outcome in context (workflow-owned); Task is a structured unit of work handed to the agent (orchestration-owned); Action is a single atomic step (agent runtime). Goal decomposition is the orchestration layer’s responsibility, not the agent’s.

The agent registry (docs/os/synedrix-os-agent-registry-v0.8.md) is the authoritative catalog of what agents exist, organized by family (control, intelligence, observability, or domain-owned domain/customer). The OS registry holds os-agt-001–os-agt-012 across three families:

  • Control: Orchestrator Agent (os-agt-001, execute), Policy Guard Agent (os-agt-002, approve — a block is final within the invocation; no human HITL decision reverses it, per ADR-OS-018), Registry & Capability Agent (os-agt-003, recommend), HITL Gateway Agent (os-agt-004, approve), Memory Curator Agent (os-agt-010, execute — the only agent that may commit durable memory), Memory Access Broker Agent (os-agt-012, approve — on the path of every memory recall)

  • Intelligence: Analytics Agent (os-agt-005, recommend), Forecasting Agent (os-agt-006, recommend), Anomaly Detection Agent (os-agt-007, recommend), the General Chat Agent (os-agt-009) — the first OS-owned agent invoked directly by a standalone LangGraph service with no owning n8n workflow (the synedrix.io website chat agent; see docs/os/synedrix-os-dgx-vercel-chat-agent-deployment-v0.5.md), and the Consolidation & Reflection Agent (os-agt-011) in the memory control plane. The chat agent is decision_scope: recommend only; its Vercel→LangGraph path bypasses the n8n governance bridge and is compliant only while no write-class tool is bound.

  • Observability: Audit & Lineage Agent (os-agt-008) — strictly read-only; must never appear in any agent’s tools_allowed

  • family must be domain or customer — domain packs may not register agents in the control or observability families. BIE agents specifically use family: customer; Capability Module agents use family: domain (they are vendor-owned IP, not customer-owned, and their owner is the contributing domain pack ID qualified with the module identifier).

  • escalation_path must terminate at an OS control agent (os-agt-001 or os-agt-004).

  • Agents with execution_scope covering financial transactions, regulated messaging, or irreversible external writes must declare approval_required.policy: true.

  • The stable agent_id prefix convention for BIE and Capability Module agents is not yet minted in the Naming Convention Spec (an open item from ADR-OS-005).

Domain-pack, Business Instance Extension (BIE), and Capability Module agent contribution rules are defined in docs/os/synedrix-os-agent-registry-v0.8.md#6.1, per ADR-OS-005.

Memory control-plane invariants

Three agents own the memory control plane (os-agt-010, os-agt-011, os-agt-012), each responsible for exactly one concern in the memory lifecycle — may this agent see this, what is worth remembering, and what is actually written. These invariants extend the general agent registry rules:

  • Memory Curator Agent (os-agt-010) is the only agent permitted to commit durable memory records. Any other agent writing directly to the episodic, semantic, procedural or profile tier is non-compliant. Its runtime_engine is n8n-aiagent because commits are deterministic and require no cyclic reasoning.
  • Memory Access Broker Agent (os-agt-012) is on the path of every memory recall and every write proposal. Scope resolution happens before the store is queried — out-of-scope memory that has already entered the process has already leaked. A denial is terminal; the requester escalates rather than reissuing a narrowed request. Its runtime_engine is n8n-aiagent because scope intersection is deterministic.
  • Consolidation & Reflection Agent (os-agt-011) holds no write access to any memory tier. It reads broadly precisely because it commits nothing, and uses langgraph runtime because consolidation is reflect-and-revise: a proposal is generated, critiqued, and revised.
  • Memory recall is a tool call bound in the resolved active_tool_set — ambient memory injection into an agent’s context is non-compliant. Erasure leaves a tombstone and graph lineage survives erasure.
  • No memory record crosses a tier boundary without a memory.record.promoted event carrying the inherited correlation_id and causation_id.

For the full specification, see Memory Fabric Spec §10 and the agent definitions in the OS Agent Registry.

Workflow contracts

Full spec: docs/os/synedrix-os-workflow-contract-spec-v0.4.md. Every workflow declares 19 fields (workflow_id, name, domain, purpose, trigger_type/trigger_source, input_contract, validation_rules, execution_pattern, agent_roles, tool_dependencies, side_effects, approval_requirements, output_contract, idempotency_strategy, retry_policy, error_policy, observability_signals, security_scope, version). Six contract rules govern workflow compliance: no implicit side effects, no free-form production outputs, high-impact workflows must be policy-aware, contracts are versioned artifacts, execution pattern must be declared, and every step must declare its type (deterministic or agent-driven) — implicit inference is supported only for backwards compatibility with v0.3-era contracts. The spec defines nine canonical execution patterns (sequential, conditional, parallel, fan-out-fan-in, iterative, consensus, hierarchical, pipeline, reflect-and-revise) and two step types (deterministic, agent-driven) — every step in sequential or pipeline patterns must declare step_type (Contract Rule 6). Deterministic steps are valid in any position within sequential and pipeline patterns; in all other patterns, every task node must be agent-driven. Composition rules allow a hierarchical parent with consensus or other child patterns, with each child declaring its own execution_pattern.

Events

Full spec: docs/os/synedrix-os-event-taxonomy-standard-v1.0.md. Every event — OS or domain — shares one 15-field envelope (event_id, tenant_id, event_type, domain, entity_type, entity_id, source_type, source_id, timestamp, correlation_id, causation_id, payload, optional policy_context, optional severity, version). tenant_id is stamped by the event layer on receipt — a producer does not set it, and if a producer supplies one it must equal the stamped value or the event is rejected. Event types are dotted, lowercase, past-tense (edition.created, not create.edition). The envelope itself is a breaking-change surface — any change to its fields, naming rules, or lifecycle rules is a major version bump. Domain packs extend the catalog under their own domain value; they never redefine the envelope and must not emit events under the reserved OS prefixes (os., workflow., policy., approval., agent., memory., goal., task.).

Outcomes

Full spec: docs/os/synedrix-os-outcome-spec-v0.3.md. Every agent invocation and every workflow execution returns the same Outcome Envelope shape, with outcome_version: "1.0" and status as the primary routing signal: success, partial, failure, blocked (Policy Guard blocked pre-execution), escalated (routed to HITL), timeout, skipped. status: success with a non-empty errors array is invalid — use partial instead. Outcomes are append-only (in agent_invocation_outcomes for agents, workflow_outcomes for workflows) and form the unit of lineage (source_outcome_id → target_outcome_id links in Neo4j with relation types invoked/contributed-to/escalated-to/governed-by). Every os.outcome.* event in the event catalog (§6.2 of the Event Taxonomy Standard) maps one-to-one to the outcome status values.

Tool authorization model

Full conceptual model: docs/os/synedrix-os-tool-authorization-model-v0.1.md; authoritative schema: docs/os/synedrix-os-agent-runtime-policy-spec-v0.4.md. Key ideas:

  • Every tool has a canonical tool_id of the form tool:<provider>-<verb> (e.g. tool:supabase-write, tool:searxng-search).
  • Every agent declares a capability ceiling in its Agent Spec tool_permissions — the maximum superset of tools it may ever use, each tagged with a side_effect_class (none / write / irreversible) and an approval_tier (auto / policy / hitl).
  • At invocation time, the active tool set passed into the runtime (n8n or LangGraph) must be a subset of the capability ceiling — this is what the executor enforces, and what makes a LangGraph agent that ignores it a non-compliant shadow runtime.
  • Tools with side_effect_class: write or higher require Policy Guard Agent (os-agt-002) approval when mcp_write_approval_required: true.
  • MCP tools are gated by mcp_tool_policy (allowlist per MCP server ID); A2A delegations are gated by a2a_tool_policy.