How the ai-memory Handoff System Facilitates Cross-Agent Communication
The ai-memory handoff system persists structured context records through the memory_handoff_begin MCP tool at session end and automatically retrieves them via the /handoff endpoint at session start, injecting the context directly into the next agent's prompt to maintain workflow continuity.
The akitaonrails/ai-memory repository provides a production-ready implementation for transferring unfinished work between AI agents. Unlike shared memory architectures, this system uses a write-once-read-once pipeline that eliminates race conditions and ensures deterministic context delivery across different agent runtimes.
Creating Handoff Records at Session End
When an agent finishes its session, the SessionEnd hook triggers the memory_handoff_begin MCP tool. This action creates a structured record defined in [crates/ai-memory-core/src/handoff.rs](crates/ai-memory-core/src/handoff.rs) (lines 60-66).
The NewHandoff struct captures:
- Origin metadata: agent identifier, workspace, project, and current working directory
- Scope: a
HandoffScopetying the record to a specific directory path - Content: a
HandoffContentpayload containing open questions or next steps
The system persists this data to the SQLite store (ai-memory-store) while simultaneously rendering a markdown representation under the wiki path sessions/<id>.md.
Ownership and Sharing Configuration
By default, handoffs belong exclusively to their creator. However, the shared: true flag makes records visible to any operator within the same project, as documented in [docs/users.md](docs/users.md) (lines 44-48). Administrators can override ownership restrictions using the any_owner: true flag on the memory_handoff_accept command.
Retrieving Context at Session Start
Every agent configured with a SessionStart hook executes the ai_memory_get_handoff helper function defined in [hooks/_lib.sh](hooks/_lib.sh) (lines 384-401). This function issues a GET request to the server's /handoff endpoint, passing the agent name and current session identifier.
The server implements precedence logic detailed in [docs/usage.md](docs/usage.md) (lines 16-26):
- Manual handoffs take priority over automatic ones
- Among automatic handoffs, the newest matching the current directory scope wins
Upon retrieval, the session-start script (e.g., [hooks/open-code/session-start.sh](hooks/open-code/session-start.sh) at line 23) prints the handoff body to stdout, causing the agent runtime to prepend this text to the user prompt.
Lifecycle Guarantees and Safety Mechanisms
Single-Use Semantics for Automatic Handoffs
Automatic handoffs implement a destructive read pattern. When an agent fetches an automatic handoff, the operation atomically marks it as accepted via the HandoffAcceptance struct ([crates/ai-memory-core/src/handoff.rs](crates/ai-memory-core/src/handoff.rs), lines 92-100). This ensures the context transfers exactly once and prevents duplicate processing.
Manual handoffs behave differently—they persist until explicitly cancelled using memory_handoff_cancel.
Scope Resolution and Idempotency
The server enforces strict scope resolution through ai_memory_store::ScopeResolver, guaranteeing that handoffs never route to incorrect projects or workspaces. Additionally, the hook library prevents accidental double-consumption by tracking session state (_lib.sh line 122), ensuring a single session never fetches the same handoff twice.
Practical Implementation Examples
Creating a Handoff in a SessionEnd Hook
# Example from hooks/open-code/session-end.sh
handoff_content=$(cat <<EOF
What remains to do:
- Verify JWT rotation
- Write unit tests for session-cookie fallback
EOF
)
ai_memory memory_handoff_begin \
--agent=open-code \
--content "$handoff_content" \
--shared=false
Automatic Retrieval in SessionStart Hooks
# From hooks/open-code/session-start.sh
HANDOFF=$(ai_memory_get_handoff "$SERVER/handoff?agent=open-code${QS}${SESSION_QS}" 2>/dev/null || true)
if [ -n "$HANDOFF" ]; then
echo "$HANDOFF"
fi
Manual Handoff Management
# List pending handoffs
ai_memory memory_handoff_list --project=my-project
# Accept a specific handoff
ai_memory memory_handoff_accept --handoff-id=123e4567-e89b-12d3-a456-426614174000
# Cancel a mistaken handoff
ai_memory memory_handoff_cancel --handoff-id=123e4567-e89b-12d3-a456-426614174000
Summary
- The ai-memory handoff system uses MCP tools and SQLite to persist context between agent sessions without shared mutable state.
- The
memory_handoff_begintool creates structured records containing origin metadata, scope, and content, storing them incrates/ai-memory-core/src/handoff.rsdata structures. - Automatic handoffs follow single-use semantics—consumed atomically on first fetch—while manual handoffs persist until cancelled.
- The
ai_memory_get_handoffhelper inhooks/_lib.shretrieves context via the/handoffendpoint, with scope resolution ensuring delivery only to matching projects and workspaces. - Context injection occurs by piping handoff content into the agent's prompt at session start, enabling seamless workflow continuation across different AI agents.
Frequently Asked Questions
How does the ai-memory handoff system prevent duplicate context injection?
The system implements a destructive read pattern for automatic handoffs. When ai_memory_get_handoff fetches a record, the server atomically marks it as accepted through the HandoffAcceptance mechanism, preventing subsequent retrievals. Additionally, session hooks track consumption state to block double-fetching within the same session.
What is the difference between automatic and manual handoffs?
Automatic handoffs are created by SessionEnd hooks and consumed automatically by the next compatible agent's SessionStart hook. They follow single-use semantics and disappear after acceptance. Manual handoffs are created explicitly by users or processes, persist indefinitely until cancelled, and can be accepted by any authorized operator through the memory_handoff_accept command.
Can handoffs be shared between different operators?
Yes. While handoffs default to private ownership, setting the shared: true flag during creation makes the record visible to any operator within the same project. Administrators can further override ownership restrictions using the any_owner: true parameter when accepting handoffs created by other users.
How does scope resolution prevent cross-project contamination?
The server uses the ai_memory_store::ScopeResolver to validate that a handoff's HandoffScope matches the requesting agent's current directory, workspace, and project. This ensures that a handoff created in one project path never injects context into an agent running in a different project, maintaining strict isolation boundaries.
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 →