Agent Graph Architecture for Multi-Agent Task Scheduling in Apache Maka
Maka's Agent Graph is a durable scheduling layer that lets the main Agent orchestrate dependent, dynamically-expanding work across many child agents without creating a second execution runtime.
The Apache Maka project implements a sophisticated agent graph architecture for multi-agent task scheduling that sits beside the existing Session-based Runtime Host. It uses a SQLite control plane to store topology, schedule intent, admission claims, and supervisor wakes while maintaining the Runtime Event Log as the single source of execution truth.
How the Agent Graph Extends the Runtime Host
Traditional multi-agent systems often duplicate runtime infrastructure or require the main Agent to approve every step. Maka's approach separates scheduling facts from execution facts.
The Runtime Host remains the sole execution authority, processing Session → AgentRun → RuntimeEventLog flows as defined in the core runtime. The Agent Graph adds a lightweight control plane that enables durable orchestration without bottlenecks:
- Topology managed in
packages/core/src/agent-graph-topology.tsmaps operators to child Sessions - Schedule revisions in
packages/core/src/agent-graph-schedule.tshandle add/stop/finish operations - Intent claims in
packages/core/src/agent-graph-control.tsenforce exactly-once admission - Supervisor wakes in
packages/runtime/src/agent-graph-supervisor-wake.tspersist root-Agent turn requests
This design allows normal work to proceed without waiting for the main Agent's approval, while still enabling comprehensive oversight through durable SQLite records.
Core Components and Data Flow
The Control Plane Primitives
The architecture defines several key abstractions that enable deterministic scheduling:
- Operator = a child Session (stable container reusable for many activations)
- Activation = an AgentRun (normal Session-inline execution producing immutable
RuntimeEvents) - Record = a bounded projection of a committed
RuntimeEvent(implemented inpackages/runtime/src/stream-graph-projection.ts) - Route = a reference-only edge making records visible to downstream operators
- Readiness = a deterministic projection (
packages/runtime/src/stream-graph-readiness.ts) deciding when an intent is runnable - Claim = pre-allocates Turn/Run IDs and marks intent as admitted via
runClaimedAgentGraphIntent
Data Flow Architecture
The system follows a strict flow from user action to execution:
- User triggers a graph-mode task through the main Agent
- Coordinator provisions operators and writes topology rows to SQLite
- Readiness projection produces runnable intents
- Coordinator claims intents with unique identifiers
- Child Sessions execute via
SessionManager.runAgent - Graph projection reads
RuntimeEvents and emits records/routes - Downstream operators activate when their readiness conditions satisfy
- Supervisor wake delivers durable requests to resume root-Agent turns at checkpoints
Execution Lifecycle
The complete lifecycle of a multi-agent task proceeds through eight precise steps that ensure durability and exactly-once semantics.
1. Schedule Updates via the Main Agent
When the main Agent initiates work, it calls update_agent_graph(add_work) which writes a schedule row to the SQLite control plane. This operation is append-only and revision-ordered for deterministic replay.
2. Operator Provisioning
The coordinator reads the schedule and provisions an operator by creating a child Session. This writes a topology row linking the operator to its Session ID. Operator provision is monotonic and retry-safe, ensuring child Sessions are never duplicated even during network partitions.
3. Intent Claiming
Before execution, the coordinator generates a readiness projection and claims the intent via runClaimedAgentGraphIntent. This binds the intent to a unique Turn/Run ID pair, preventing duplicate execution on retries. The claim is persisted in packages/runtime/src/stream-graph-admission.ts.
4. Child Session Execution
With claims established, the coordinator invokes normal child-Session execution. The child AgentRun writes RuntimeEvents to the event log exactly as non-graph Sessions do.
5. Graph Projection
The readCommittedAgentGraphProjection function (in packages/runtime/src/stream-graph-projection.ts) reads committed RuntimeEvents and transforms them into AgentGraphRecord objects. Only committed events become graph records, guaranteeing immutable facts.
6. Dynamic Expansion
When a record satisfies downstream operator readiness policies (such as map or all_settled in stream-graph-readiness.ts), steps 3-5 repeat automatically. This allows the graph to expand dynamically without main Agent intervention.
7. Supervisor Wake Delivery
The supervisor wake stores a durable request to start a root-Agent turn. When the graph reaches a useful checkpoint—defined as completion of a determinate set of records—the wake delivers to the main Agent.
8. Root Agent Continuation
The main Agent reads the current graph state via view_agent_graph, fetches authoritative child output through agent_output, and may add more work or call finish to complete the schedule.
Safety Invariants and Guarantees
The architecture enforces six critical invariants that enable crash-safe multi-agent orchestration:
- Append-only schedule — All schedule updates are revision-ordered and idempotent, guaranteeing deterministic replay across restarts.
- Monotonic operator provision — Child Session creation is retry-safe; duplicate provision attempts are detected and deduplicated via
packages/core/src/agent-graph-topology.ts. - Exactly-once claim binding — Each intent maps to a unique Turn/Run ID through the claim mechanism in
stream-graph-admission.ts. - Committed-event projection — Graph records only reference
RuntimeEvents that have durably committed to the event log. - Supervisor wake timing — Wakes deliver only after root AgentRun completion, preventing lost or premature notifications.
- Recovery from logs — System rebuilds graph state from SQLite rows and Runtime logs, not from in-memory state, enabling crash-safe continuation.
These invariants are verified by the test suite in packages/runtime/src/__tests__/stream-graph-*.test.ts.
Working with the Agent Graph API
Adding Work to the Graph
To initiate a new operator that runs a specialist agent:
import { update_agent_graph } from '@maka/core/graph-command';
// Add a new operator that runs the "local_read" specialist
await update_agent_graph({
add_work: [
{
work_id: 'w1',
operator_id: null, // null → provision a new operator
agent_id: 'local_read', // catalog agent to spawn
instruction: 'Inspect storage layout',
input_ids: [], // no upstream records yet
},
],
});
This writes to agent_graph_schedule via packages/core/src/agent-graph-schedule.ts.
Querying Current Graph State
To inspect operators and ready work:
import { view_agent_graph } from '@maka/core/graph-command';
const graph = await view_agent_graph();
console.log('Operators:', graph.operators);
console.log('Ready work IDs:', graph.readyWorkIds);
The implementation in packages/core/src/graph-command.ts reads the SQLite control plane and the projection.
Reading Child Agent Output
To fetch results from a completed child activation:
import { agent_output } from '@maka/core/graph-command';
const output = await agent_output({
childSessionId: 'sess-123',
runId: 'run-456',
view: 'result', // only the final model answer
});
console.log(output.text);
This retrieves authoritative RuntimeEvent data from the event log.
Finishing a Schedule
To mark work as complete and stop further admission:
await update_agent_graph({
finish: {
work_ids: ['w1', 'w2'], // IDs of records that should be the final answer
},
});
The coordinator stops admission after processing this finish row.
Key Source Files
| Area | File | Purpose |
|---|---|---|
| Control-plane schema | packages/storage/src/agent-graph-control-store.ts |
SQLite tables for topology, schedule, claims, wakes |
| Schedule API | packages/core/src/agent-graph-schedule.ts |
add_work, stop, finish definitions |
| Topology management | packages/core/src/agent-graph-topology.ts |
Monotonic operator creation, child-Session linking |
| Event projection | packages/runtime/src/stream-graph-projection.ts |
Turns RuntimeEvents into AgentGraphRecords |
| Readiness policies | packages/runtime/src/stream-graph-readiness.ts |
map and all_settled deterministic intents |
| Admission control | packages/runtime/src/stream-graph-admission.ts |
runClaimedAgentGraphIntent exact-once logic |
| Coordinator loop | packages/runtime/src/stream-graph-dispatch.ts |
Drive-to-quiescence, concurrent operator execution |
| Supervisor wakes | packages/runtime/src/agent-graph-supervisor-wake.ts |
Durable wake rows, retry logic |
| Public API | packages/runtime-host/src/server/agent-graph-coordinator.ts |
Exposes view_agent_graph, update_agent_graph, agent_output over RPC |
Summary
- The Agent Graph adds a SQLite control plane to Maka's existing Runtime Host, enabling durable multi-agent scheduling without secondary execution infrastructure.
- Operators (child Sessions) and Activations (AgentRuns) separate container lifecycle from execution instances.
- The exactly-once claim mechanism in
stream-graph-admission.tsprevents duplicate work during retries. - Graph projections transform committed
RuntimeEvents into records that trigger downstream readiness. - Supervisor wakes provide durable checkpoints for root-Agent oversight without blocking child execution.
- All scheduling state recovers from SQLite and the Runtime Event Log, eliminating dependency on in-memory coordinator state.
Frequently Asked Questions
What is the difference between an Operator and an Activation in Maka's Agent Graph?
An Operator is a stable child Session container that can be reused across multiple executions, while an Activation is a specific AgentRun instance that produces RuntimeEvents. According to packages/core/src/agent-graph-topology.ts, operators persist across graph revisions, whereas activations represent point-in-time executions within those operators.
How does the Agent Graph ensure exactly-once execution of tasks?
The graph uses a claim mechanism implemented in packages/runtime/src/stream-graph-admission.ts. Before executing any intent, the coordinator calls runClaimedAgentGraphIntent to pre-allocate Turn/Run IDs and persist the claim to SQLite. If the coordinator crashes and retries, it detects existing claims and skips duplicate execution, ensuring exactly-once semantics.
Can the Agent Graph recover from coordinator crashes without losing work?
Yes. The architecture recovers by rebuilding state from the Runtime Event Log and SQLite control plane rather than in-memory state. As documented in agent-graph-control-store.ts, all topology, schedule revisions, and claims are durable. When the coordinator restarts, it replays the append-only schedule log and resumes projections from the last committed event.
How does the main Agent communicate with child agents in the graph?
The main Agent does not directly message child agents. Instead, it writes schedule revisions via update_agent_graph, and the coordinator provisions operators independently. The main Agent reads results asynchronously through view_agent_graph and agent_output only when a supervisor wake indicates the graph has reached a useful checkpoint, preventing the main Agent from becoming a bottleneck.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →