Back to Home

Event sourcing for agents: declarative assembly of AI systems

The article examines the application of event sourcing in multi-agent systems using the zymi framework example. It shows how the declarative approach solves the mutable state problem, ensures reproducibility, and simplifies integration with LLM. Examples of configurations and architectural benefits are provided.

Why mutable state kills your agent systems (and how to fix it)
Advertisement 728x90

Declarative Agent Assembly: How Event Sourcing Solves the Mutable State Problem

Modern multi-agent systems based on LLMs face a fundamental challenge: managing state via mutable state leads to instability and debugging headaches. The solution comes from an unexpected source—data engineering practices. The new zymi framework applies event sourcing and declarative description principles, familiar from dbt, to build reliable agent-oriented systems.

Declarative Approach Instead of Imperative Code

Traditional frameworks like LangGraph require detailed instructions on how to process data through mutable state. This creates several critical issues:

  • State turns into a messy dump with hidden dependencies
  • Every change demands manual synchronization
  • Debugging becomes a slog of hunting through print logs

zymi flips the paradigm: you describe what needs to be done using YAML configs, and the engine handles execution automatically. The project structure mirrors a dbt project:

Google AdInline article slot
zymi-research/
├── agents/
│  ├── researcher.yml
│  └── writer.yml
├── pipelines/
│  └── research.yml
├── tools/
└── project.yml

Each agent is defined via a declarative manifest. For example, the researcher agent:

name: researcher
description: "Research agent — searches the web, scrapes pages, and stores findings in memory"
model: ${default_model}
system_prompt: |
  You are a thorough research assistant. Your job is to find accurate,
  up-to-date information on the given topic.

tools:
  - web_search
  - web_scrape
  - write_memory
max_iterations: 15

Tools are also described declaratively. The web_search implementation via Tavily API:

name: web_search
description: "Search the web for information on a given query"
parameters:
  type: object
  properties:
    query:
      type: string
      description: "Search query"
  required: [query]

implementation:
  kind: http
  method: POST
  url: "https://api.tavily.com/search"
  headers:
    Authorization: "Bearer ${env.TAVILY_API_KEY}"
  body_template: '{"query": "${args.query}", "max_results": 5}'

A pipeline chains agents into steps with dependencies:

Google AdInline article slot
name: research
steps:
  - id: search_web
    agent: researcher
    task: "Search the web for information about: ${inputs.topic}"

  - id: analyze
    agent: researcher
    task: "Analyze findings and store structured summary"
    depends_on: [search_web]

  - id: write_report
    agent: writer
    task: "Write report to ./output/report.md"
    depends_on: [analyze]

Run the pipeline via CLI:

zymi run research -i topic="Event sourcing in AI"

Event Sourcing: From Immutable Events to Reproducibility

The key distinction of zymi from LangGraph is ditching mutable state for an event-sourced architecture. All interactions are logged as immutable events in a cryptographically verified chain. Each event includes:

  • Hash of the previous event (ensures chain integrity)
  • Operation data
  • Timestamp
  • Event source

This model delivers three critical advantages:

Google AdInline article slot
  • Full Traceability — any result can be reconstructed from the event chain
  • Built-in Audit Trail — all changes are logged effortlessly
  • Operation Safety — the monitor evaluates intentions before execution

Here's a snippet from an execution log:

#4    10:50:52.806 intention_emitted source=orchestrator
  call_custom_tool data={"type":"CallCustomTool","data":{"tool_name":"web_search"}}
#5    10:50:52.806 intention_evaluated source=orchestrator
  call_custom_tool -> approved
#49   11:20:15.321 intention_emitted source=orchestrator
  write_file data={"path":"output/report.md"}
#50   11:20:15.322 intention_evaluated source=orchestrator
  write_file -> requires_approval

This shows how the system first emits an intention to perform an operation (intention_emitted), then the monitor decides whether to approve it (intention_evaluated). On the file write attempt, the monitor required approval—a safeguard impossible with direct state mutation.

Benefits for Developers and LLMs

The declarative approach offers practical wins, especially in the era of generative AI:

  • Reduced Complexity for LLMs — YAML configs are simpler to generate than imperative code
  • Strict Validation Schema — JSON Schema prevents config errors
  • Parallel Execution — the engine automatically identifies independent steps
  • Reproducibility — any run can be replayed from the event log

Experiments show that LLM-generated pipelines for zymi take 30-40% fewer iterations than equivalent LangGraph code. This stems from:

  • No manual state management
  • Clear responsibility boundaries between components
  • Static config validation

What Matters

  • Declarative over Imperative — describing what to do, not how, cuts cognitive load
  • Event Sourcing as the Foundation — immutable events ensure reproducibility and safety
  • Integration with LLM Development — structured configs are easier for AI to generate and refine
  • Cryptographic Integrity — the hash-chain guarantees execution history authenticity
  • Intention Monitoring — a dedicated layer vets operations to block unwanted actions

The zymi framework demonstrates how data engineering concepts can tackle systemic challenges in agent-oriented programming. Moving from mutable state to event-sourced architecture doesn't just simplify development—it unlocks new possibilities for controlling and analyzing AI agent behavior. For technical pros, this shifts from brittle systems to reliable, traceable solutions where every step has verifiable proof and reproducibility.

— Editorial Team

Advertisement 728x90

Read Next