The event lattice
Every other agentic framework puts a scheduler at the center: “now run agent B.” Axocoatl puts a coordination fabric at the center, and lets the agents decide for themselves when they’re ready.
That fabric is the event lattice.
How it works
Section titled “How it works”The lattice is a shared bulletin board for events. Agents publish events
when they finish work (or fail, or get interrupted). Each published event is
broadcast to every agent — there’s no edge-addressed routing. Every agent
watches for events it cares about and accumulates signal from them. When an
agent’s threshold is crossed — usually one TaskCompleted from each
dependency — it wakes up and runs.
Concretely: an entry agent (no dependencies) has threshold 1.0, so a single
UserInput signal (strength 1.0) activates it. A downstream agent with N
dependencies has threshold 0.5 × N, and each upstream TaskCompleted
contributes 0.5 — so it fires exactly once all N of its dependencies have
completed. (Both are tunable per agent via activation_threshold /
activation_decay.)
There’s no orchestrator deciding the order. The order is whatever the dependency graph implies. The lattice is what makes the ordering happen.
A two-agent example
Section titled “A two-agent example”agents: - id: researcher provider: ollama model: llama3.2 depends_on: [] - id: summarizer provider: ollama model: llama3.2 depends_on: [researcher]- You fire the workflow. The lattice publishes a
WorkflowStartedevent tagged with the workflow id. researcherhas no dependencies, so its threshold (zero events needed) is already met. It activates immediately.- When
researcherfinishes, the actor publishes aTaskCompletedevent withagent_id: researcher. summarizer’s threshold is “oneTaskCompletedfromresearcher.” That’s now met. The lattice activatessummarizer. Its input is the outputresearcherpublished.summarizerruns, publishes its ownTaskCompleted, and the workflow ends.
No scheduler. No central state machine. Just events on a shared lattice.
Why this matters
Section titled “Why this matters”The lattice also unlocks:
- Multi-agent for the same skill. If two agents both hold a Skill
that reacts to
BugReportFiled, the lattice activates every holder — it’s a fan-out, you don’t pre-assign. Narrowing that fan-out to a single best-fit holder via an auction is a deliberate non-goal for the lattice: arbitration lives in the coordinator (below), not here. - Proactive agents. An agent can declare it reacts to a system event
(
EveryMorningAt8am,NewSupportEmail). The lattice activates it without you doing anything. - Skills routing. A Skill declares the events it emits and reacts to; the lattice wires it to whichever agent holds it. Move the Skill to a different agent, and the lattice routes there instead.
- Interrupts. An agent can pause itself, publish an
Interruptedevent, and wait for human input. The lattice picks it back up onResumed.
Where auctioning lives: the coordinator
Section titled “Where auctioning lives: the coordinator”The lattice itself never picks a winner — it broadcasts and lets thresholds decide. When you do want a single agent chosen for a task, that’s the job of the coordinator role, a separate mechanism that ships today.
An agent with role: coordinator spawns a pool of role: worker agents at
runtime, decomposes its task into subtasks, and assigns each subtask to a
worker via a capability + budget auction: every worker bids, and the best
fit by required tools and available budget wins. This is real, on the live
execute path — not roadmap.
So the two ideas live in different places by design: the lattice fans out to every holder; the coordinator arbitrates. There is no auction inside the lattice, and adding one is a non-goal.
Watch it happen
Section titled “Watch it happen”In the dashboard, open Studio. The whole lattice is the canvas; every agent is a node. When an event fires that activates an agent, the node pulses. Drag the canvas around, click nodes to inspect, and use the left rail to filter by team or jump to a specific agent.
Every pulse you see is a real lattice event. Studio is a window onto the actual coordination layer — not a rendering layer that lies for the demo.