How ai-memory Facilitates Cross-Agent Handoffs: Architecture and Implementation
ai-memory enables secure cross-agent handoffs through a centralized handoff table with exactly-once claim semantics, exposing lifecycle operations via MCP and HTTP APIs while enforcing fine-grained ownership and visibility rules.
The ai-memory framework from the akitaonrails/ai-memory repository provides a robust mechanism for autonomous agents to transfer task context through structured cross-agent handoffs. By persisting handoff metadata in SQLite and routing state changes through a dedicated admission layer, the system ensures that only one agent can claim a given handoff while maintaining full audit trails across the codebase.
Core Handoff Data Model
The foundation of cross-agent communication rests on the Handoff struct defined in crates/ai-memory-core/src/handoff.rs. This structure encapsulates all metadata required to resume a task, including fields for summary, open_questions, next_steps, project, agent, and an optional owner representing the agent that created the handoff. When an agent initiates a transfer, this data model serializes the current execution context into a format that receiving agents can ingest without requiring direct memory sharing.
Admission Lifecycle for State Transitions
All handoff state changes are routed through the admission layer in crates/ai-memory-wiki/src/admission.rs. The AdmissionOp enum defines three distinct operations that govern the handoff lifecycle:
handoff_begin– Inserts a new row into the handoff table without creating a wiki page, establishing the initial context for transfer.handoff_accept– Marks a pending handoff as claimed, implementing exactly-once claim semantics by atomically decrementing the open handoff count to prevent double-claims.handoff_cancel– Removes a pending handoff from the queue, ensuring no orphaned rows remain in the database.
These operations are defined at lines 106-108 of the admission module, creating a state machine that guarantees predictable transitions between pending, claimed, and cancelled states.
MCP and HTTP API Surface
The framework exposes handoff functionality through dual interfaces: the Model Context Protocol (MCP) server and RESTful HTTP endpoints. In crates/ai-memory-mcp/src/server.rs, the structs HandoffBeginArgs, HandoffAcceptArgs, and HandoffCancelArgs define the request payloads for MCP clients (lines 962-1028). These structures mirror the admission operations, allowing MCP-compatible agents to initiate and claim handoffs programmatically.
The web API in crates/ai-memory-web/src/routes/api.rs provides corresponding HTTP routes:
GET /workspaces/{workspace}/projects/{project}/handoffs– Retrieves a list of open handoffs filtered by visibility rules.POST /workspaces/{workspace}/projects/{project}/handoffs– Creates a new handoff via thehandoff_beginadmission operation.
These routes are implemented at lines 62-63 of the API module, providing language-agnostic access to the handoff system.
Visibility and Ownership Controls
ai-memory implements sophisticated visibility rules that determine which agents can view or claim specific handoffs. The system distinguishes between owned handoffs (tied to a specific agent) and unowned handoffs (visible to all agents in the workspace). Owner agents see their handoffs in full detail, while other agents receive only the summary field unless the handoff is explicitly unowned.
Root users can bypass these restrictions using the ?all_owners=true query parameter to audit all pending handoffs across the system. The test suite in crates/ai-memory-web/tests/suite/routes.rs verifies these semantics, including scenarios where owned handoffs are hidden from unnamed callers (lines 1978-2012).
Cross-Agent Workflow Example
A typical handoff between Agent A and Agent B proceeds through these atomic steps:
- Agent A creates a handoff via the MCP
handoff_beginoperation or HTTP POST, embedding the current task context including open questions and next steps. - The system persists the handoff row in the SQLite database and returns a unique handoff ID.
- Agent B queries the workspace API for open handoffs, filtering for relevant projects or summaries.
- Agent B invokes
handoff_acceptwith the specific handoff ID, triggering the atomic claim operation in the admission layer. - The acceptance succeeds only if the handoff remains unclaimed; concurrent claim attempts receive conflict responses, enforcing exactly-once semantics.
- Once claimed, subsequent queries show the handoff as unavailable, and Agent B receives the full payload to resume execution.
// Agent A: Initiate handoff
let begin = HandoffBeginArgs {
workspace: "production".into(),
project: "data-pipeline".into(),
summary: "Resume ETL after schema validation".into(),
open_questions: vec!["Handle null timestamps?".into()],
next_steps: vec!["Transform JSON to Parquet".into()],
owner: Some("agent-alpha".into()),
};
let handoff_id = mcp_client.handoff_begin(begin).await?;
// Agent B: Discover and claim
let handoffs: Vec<Handoff> = http_client
.get("/workspaces/production/projects/data-pipeline/handoffs")
.await?;
let target = handoffs.iter().find(|h| h.id == handoff_id).unwrap();
let accept = HandoffAcceptArgs {
workspace: "production".into(),
project: "data-pipeline".into(),
handoff_id: target.id,
};
mcp_client.handoff_accept(accept).await?;
Persistence and Concurrency Guarantees
Handoff durability relies on a single-writer SQLite actor implemented in the ai-memory-store crate. All inserts, updates, and deletes are serialized through this actor, preventing race conditions during concurrent claim attempts. The handoff table maintains indexes on (workspace_id, project_id, handoff_id), ensuring efficient lookups while preserving the global identity invariant documented in the project's architecture specification.
Additionally, the ai-memory-workstream crate integrates handoff events into managed workstreams, allowing agents to resume tasks after handoffs without losing execution context (see crates/ai-memory-workstream/src/transcript.rs, line 791).
Summary
- ai-memory implements cross-agent handoffs through a centralized SQLite-backed table with strict admission controls.
- The admission layer in
ai-memory-wikiprovides atomic operations for beginning, accepting, and canceling handoffs. - Exactly-once claim semantics prevent duplicate processing when multiple agents attempt to claim the same handoff simultaneously.
- Ownership and visibility rules restrict access to sensitive handoff details while allowing public unowned handoffs for open collaboration.
- Dual MCP and HTTP APIs enable integration with both AI-native clients and traditional web services.
Frequently Asked Questions
How does ai-memory prevent race conditions when multiple agents claim the same handoff?
The system prevents race conditions through an atomic handoff_accept operation in the admission layer. When an agent attempts to claim a handoff, the admission controller checks the current state within the single-writer SQLite transaction. Only the first claimant successfully decrements the open handoff count; subsequent requests receive a conflict error, enforcing exactly-once semantics without requiring distributed locks.
What distinguishes owned handoffs from unowned handoffs?
Owned handoffs are explicitly tied to a specific agent identifier in the owner field, restricting full payload visibility to that agent and root users. Unowned handoffs omit the owner field, making them visible to all authenticated agents within the workspace. This distinction enables both private task delegation between specific agents and public task queues where any available agent can claim work.
Can external orchestration systems integrate with ai-memory handoffs?
Yes. External systems can integrate through the HTTP API defined in ai-memory-web or the MCP protocol implemented in ai-memory-mcp. The REST endpoints support standard CRUD operations on handoffs, while the MCP interface provides structured arguments for handoff lifecycle management. Both interfaces respect the same admission and visibility rules, ensuring consistent behavior regardless of the client implementation.
How are handoffs preserved across agent restarts or system crashes?
Handoffs achieve durability through SQLite persistence in the ai-memory-store crate. Because handoffs exist as rows in a database table rather than in-memory state, they survive agent restarts, process termination, or system crashes. The single-writer actor model ensures that pending handoffs remain in a consistent state, allowing agents to query and claim handoffs that were created before a restart occurred.
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 →