# Understanding ObservationKind Values in the ai-memory Rust Library

> Explore the ten ObservationKind values in the ai-memory Rust library like SessionStart and UserPrompt. Classify agent events for persistent storage.

- Repository: [Fabio Akita/ai-memory](https://github.com/akitaonrails/ai-memory)
- Tags: api-reference
- Published: 2026-09-10

---

**The ai-memory library defines ten distinct ObservationKind enum variants—such as SessionStart, UserPrompt, and PreToolUse—that classify agent lifecycle events and serialize them as kebab-case strings for persistent storage.**

The `ai-memory` repository by AkitaOnRails provides a structured memory system for AI agents, capturing every significant event during a session. At the core of this telemetry system lies the `ObservationKind` enum, defined in [`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs), which categorizes each captured moment with type-safe variants that map to wire-format strings.

## Complete Reference of ObservationKind Values

The `ObservationKind` enum contains ten variants representing distinct lifecycle moments of an agent session. Each variant persists as a specific kebab-case string via the `as_str()` method.

### Session Lifecycle Events

- **SessionStart**: Marks when a new session begins, recording the current working directory and agent details. Stored as `session-start`.
- **SessionEnd**: Indicates the session is closed permanently. Stored as `session-end`.
- **Stop**: Signals the agent finishes its current turn (e.g., after a `/stop` command). Stored as `stop`.

### User Interaction Events

- **UserPrompt**: Captures when the user submits a prompt to the model. Stored as `user-prompt`.
- **Notification**: Records when the agent emits a notification message. Stored as `notification`.

### Tool Execution Events

- **PreToolUse**: Indicates the agent is about to invoke a tool. Stored as `pre-tool-use`.
- **PostToolUse**: Signifies the tool call has finished and its outcome is known. Stored as `post-tool-use`.

### Context Management Events

- **PreCompact**: Triggered when context-window pressure initiates a compaction event. Stored as `pre-compact`.
- **PostCompaction**: Marks completion of the compaction step (Devin-specific implementation). Stored as `post-compaction`.

### Fallback Category

- **Other**: Catch-all for unrecognized or custom events, stored unchanged as `other`.

## String Serialization and Flexible Parsing

According to the source code in [`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs), the enum implements bidirectional conversion between variants and strings.

The `as_str()` method serializes variants to kebab-case for database storage and wire transmission. Conversely, the `FromStr` implementation enables flexible deserialization, accepting **kebab-case**, **snake_case**, or **PascalCase** formats (e.g., `"session_start"` or `"SessionStart"` both parse to `ObservationKind::SessionStart`).

```rust
use ai_memory_core::ObservationKind;

// Convert enum to canonical kebab-case string
let kind = ObservationKind::UserPrompt;
assert_eq!(kind.as_str(), "user-prompt");

// Parse from various string formats
let from_pascal: ObservationKind = "PostToolUse".parse().unwrap();
let from_snake: ObservationKind = "pre_tool_use".parse().unwrap();
assert_eq!(from_pascal, ObservationKind::PostToolUse);
assert_eq!(from_snake, ObservationKind::PreToolUse);

```

## Practical Usage in the Codebase

Developers interact with `ObservationKind` values when creating new observations or mapping hook events. In [`crates/ai-memory-hooks/src/payload.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-hooks/src/payload.rs), the `HookEvent` type converts to `ObservationKind` via the `to_observation_kind()` method, bridging external triggers with the internal storage system.

When inserting observations into the store, specify the kind variant directly:

```rust
use ai_memory_core::{ObservationKind, NewObservation};

let new_obs = NewObservation {
    session_id: sess_id,
    workspace_id: ws_id,
    project_id: proj_id,
    kind: ObservationKind::PreToolUse,  // Classify as pre-tool execution
    extension: None,
    source_event: None,
    title: "write-file".into(),
    body: "tool_family: \"file\"".into(),
    importance: 5,
};
store.insert_observation(new_obs)?;

```

The unit tests in [`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs) (lines 63-95) verify round-trip serialization and the tolerant parsing behavior, ensuring that storage strings consistently map back to their enum variants.

## Summary

- **Ten variants** define the complete taxonomy of agent events in `ai-memory`, from `SessionStart` to `SessionEnd`.
- **Kebab-case strings** provide the canonical wire format (`user-prompt`, `pre-tool-use`), while **flexible parsing** accepts snake_case and PascalCase.
- **Core definition** resides in [`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs), with **event mapping** implemented in [`crates/ai-memory-hooks/src/payload.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-hooks/src/payload.rs).
- **Type-safe construction** uses `ObservationKind` variants directly when building `NewObservation` structs for persistent storage.

## Frequently Asked Questions

### What is the difference between PreToolUse and PostToolUse?

**PreToolUse** signals the moment immediately before the agent invokes a tool, capturing intent and parameters, while **PostToolUse** records the completion state after the tool executes and returns results. Both variants store as `pre-tool-use` and `post-tool-use` respectively, enabling precise timing analysis of tool latency and success rates.

### How does ai-memory handle unknown ObservationKind values?

The **Other** variant acts as a catch-all for unrecognized or custom events not defined in the standard enum. When parsing arbitrary strings, values that do not match known variants map to `ObservationKind::Other` and persist unchanged, preventing deserialization failures while maintaining data integrity.

### Can ObservationKind values be parsed from different string formats?

Yes, the implementation accepts **kebab-case** (`user-prompt`), **snake_case** (`user_prompt`), and **PascalCase** (`UserPrompt`) formats through the `FromStr` trait. This flexibility allows the system to ingest events from various external sources without strict preprocessing requirements.

### Where is ObservationKind defined in the source code?

The enum definition, string conversion logic, and unit tests reside in **[`crates/ai-memory-core/src/observation.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-core/src/observation.rs)**. Additional usage and event mapping occur in **[`crates/ai-memory-hooks/src/payload.rs`](https://github.com/akitaonrails/ai-memory/blob/main/crates/ai-memory-hooks/src/payload.rs)**, where `HookEvent` types convert to `ObservationKind` via the `to_observation_kind()` method.