What Is the /hook Endpoint in ai-memory? A Complete Technical Guide

The /hook endpoint is the central HTTP ingestion point that receives lifecycle events from AI coding agents, sanitizes the payload to remove secrets and PII, and persists observations to a SQLite database for durable knowledge storage.

The ai-memory project provides a persistent memory layer for AI coding assistants like Claude-code, Open-code, and Codex. The /hook endpoint serves as the critical gateway that transforms transient agent interactions into searchable, project-specific knowledge by processing webhook-style notifications from various coding agents.

Core Responsibilities of the /hook Endpoint

HTTP POST Request Handling

The endpoint is defined in crates/ai-memory-mcp/src/routes/hook.rs as an Axum route that accepts POST requests at the path /hook. Agents send requests with query parameters specifying the event type, agent identifier, and scope:

// In crates/ai-memory-mcp/src/routes/hook.rs
pub async fn handle_hook(
    Query(params): Query<HookParams>,
    Json(payload): Json<RawObservation>,
) -> Result<StatusCode, ApiError> {
    // Processing logic
}

The HookParams struct parses event (e.g., session-start, user-prompt, post-tool-use), agent (e.g., claude-code, open-code), and scope (the repository context) from the query string.

Payload Sanitization Pipeline

Before persistence, every observation passes through the sanitizer implemented in crates/ai-memory-hooks/src/sanitizer.rs. This component strips personally identifiable information, secrets, API keys, and enforces content size limits to ensure safe storage.

let sanitized = sanitizer::sanitize(payload)?;

The sanitize() function returns a cleansed version of the RawObservation that is safe for long-term retention and search indexing.

Atomic Storage Operations

Once sanitized, the observation is transformed into a NewObservation struct (defined in crates/ai-memory-core/src/observations.rs) and submitted to the single-writer SQLite actor located in crates/ai-memory-store/src/writer.rs. This architecture guarantees atomic writes and maintains the FTS5 full-text search index without blocking the HTTP response.

store::writer::submit_observation(sanitized, params.scope).await?;

Fire-and-Forget Response Pattern

The endpoint implements an asynchronous ingestion model. After validating and queueing the observation for storage, it immediately returns HTTP 202 Accepted, allowing AI agents to continue execution without waiting for database commits:

Ok(StatusCode::ACCEPTED)   // 202 – fire‑and‑forget

Technical Implementation in the ai-memory Source Code

The complete request lifecycle spans three core crates. Here is the annotated flow from the Axum handler through to persistent storage:

// crates/ai-memory-mcp/src/routes/hook.rs
use axum::{extract::Query, http::StatusCode, Json};

pub async fn handle_hook(
    Query(params): Query<HookParams>,
    Json(payload): Json<RawObservation>,
) -> Result<StatusCode, ApiError> {
    // 1. Sanitize input to remove secrets and PII
    let sanitized = sanitizer::sanitize(payload)?;
    
    // 2. Submit to the single-writer actor for SQLite insertion
    store::writer::submit_observation(sanitized, params.scope).await?;
    
    // 3. Return immediately while background processing continues
    Ok(StatusCode::ACCEPTED)
}

The submit_observation function in crates/ai-memory-store/src/writer.rs handles the actual INSERT operation and updates the search index, ensuring data consistency even under concurrent write loads from multiple agents.

Client-Side Integration: Hook Scripts

AI agents interact with the endpoint through shell scripts located in the hooks/ directory. For example, the Open-code agent uses hooks/opencode/session-start.sh to notify ai-memory when a new session begins:


# Example from hooks/opencode/session-start.sh

SERVER="http://localhost:49374"
AGENT="open-code"
EVENT="session-start"
QS="&scope=repo%3Amy-repo%3Amain"

ai_memory_post_hook "$SERVER/hook?event=$EVENT&agent=$AGENT$QS" >/dev/null 2>&1

The ai_memory_post_hook helper function wraps curl to send the POST request with the appropriate JSON payload containing the observation data.

Data Flow Architecture

The complete data flow from agent action to searchable knowledge follows these steps:

  1. Agent triggers event – The AI coding tool executes a lifecycle hook (e.g., after a tool use or prompt completion).
  2. Script POSTs to /hook – The shell wrapper sends the observation to http://<ai-memory-host>/hook with event and agent parameters.
  3. Sanitizer processes payload – The sanitizer::sanitize() function in crates/ai-memory-hooks removes sensitive data.
  4. Writer persists data – The SQLite actor in crates/ai-memory-store atomically inserts the record and updates the FTS5 index.
  5. Data becomes queryable – Observations are accessible via the search API for retrieval and embedding generation.

Once stored, observations can be retrieved via the REST API:

curl "http://localhost:49374/api/v1/observations?scope=repo%3Amy-repo%3Amain"

Summary

  • The /hook endpoint in ai-memory receives HTTP POST requests from AI coding agents at crates/ai-memory-mcp/src/routes/hook.rs.
  • It enforces data safety through the sanitizer::sanitize() function in crates/ai-memory-hooks/src/sanitizer.rs, which strips secrets and PII.
  • Sanitized observations are stored via the single-writer actor in crates/ai-memory-store/src/writer.rs, ensuring atomic SQLite transactions.
  • The endpoint returns HTTP 202 Accepted immediately, implementing a fire-and-forget pattern that prevents agent blocking.
  • Hook scripts in the hooks/<agent>/ directories handle client-side integration for tools like Open-code and Claude-code.

Frequently Asked Questions

What HTTP method does the /hook endpoint accept?

The /hook endpoint accepts POST requests only. According to the source code in crates/ai-memory-mcp/src/routes/hook.rs, it expects a JSON payload containing the observation data and query parameters for event, agent, and scope.

How does ai-memory handle sensitive data in hook payloads?

The system passes every incoming payload through a sanitizer implemented in crates/ai-memory-hooks/src/sanitizer.rs. This function removes personally identifiable information, API keys, secrets, and other unsafe content before the data reaches persistent storage, ensuring that only cleansed observations are indexed and retained.

What database does ai-memory use for storing observations?

Ai-memory uses SQLite as its backing store, accessed through a single-writer actor pattern defined in crates/ai-memory-store/src/writer.rs. This design uses FTS5 (Full-Text Search version 5) for indexing observations, allowing fast semantic and keyword searches across project histories.

Can I query stored observations after they are ingested?

Yes, once an observation is accepted by the /hook endpoint and processed by the writer actor, it becomes available through the search API. You can query observations by scope using the /api/v1/observations endpoint, making the data accessible for retrieval-augmented generation (RAG) workflows and project wiki generation.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →