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

> Discover the role of the /hook endpoint in ai-memory. This guide explains how it ingests AI agent events, sanitizes data, and stores observations for durable knowledge.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: deep-dive
- Published: 2026-09-12

---

**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`](https://github.com/akitaonrails/ai-memory/blob/main/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:

```rust
// 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`](https://github.com/akitaonrails/ai-memory/blob/main/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.

```rust
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`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observations.rs)) and submitted to the single-writer SQLite actor located in [`crates/ai-memory-store/src/writer.rs`](https://github.com/akitaonrails/ai-memory/blob/main/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.

```rust
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:

```rust
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:

```rust
// 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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/hooks/opencode/session-start.sh) to notify ai-memory when a new session begins:

```sh

# 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:

```bash
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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/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`](https://github.com/akitaonrails/ai-memory/blob/main/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.