Event Grain

What is an Event grain?

An Event grain records something that happened — a message, a system notification, a behavioral occurrence, or any discrete moment worth preserving in the context database. Events carry a single required content field and form the temporal backbone of AI agent memory.

Events are the most general-purpose grain type for recording history. They differ from Actions (which track tool invocations with structured input/output) and Observations (which carry observer identity metadata). An Event says “this happened” without asserting who perceived it or what tool produced it. This makes Events the right choice for conversation messages, system logs, user behavior records, and any narrative-style memory.

The text representation used for embedding and BM25 indexing is the content field directly. Events pair naturally with the valid_from and valid_to common fields for temporal queries — set valid_from to the Unix timestamp of when the event occurred and query by time range to reconstruct a timeline. The temporal_type common field defaults to "event" for this grain type.

FieldTypeRequiredDescription
contentstringyesFree-text description of what happened
subjectstringnoOptional subject for triple-store indexing
objectstringnoOptional object for triple-store indexing

Plus all common fields (confidence, tags, namespace, etc.).

How do I create an Event?

Send the event through the /batch-add endpoint with grain_type: "event" and a content field. The /add endpoint is reserved for Belief triples, so all non-Belief grains use /batch-add.

You can batch multiple events in a single request, which reduces round trips when ingesting conversation histories or log streams. Each event in the batch gets its own content-address hash. Use namespace to group related events (for example, "session-42" for all events in a chat session) and tags to add searchable labels.

For autonomous memory pipelines that ingest events from external systems, set source_type to indicate the origin ("user", "agent", "system", "webhook") and valid_from to the original event timestamp rather than the ingestion time.

import areev

db = areev.open("./data")
h = db.add("event", {"content": "User completed onboarding flow"})
POST /api/memories/default/batch-add
Content-Type: application/json

{
  "grains": [
    {"grain_type": "event", "fields": {"content": "User completed onboarding flow"}}
  ]
}
areev add event content="User completed onboarding flow"

How do I query Events by time?

Use the valid_from and valid_to fields to scope queries to a time range, or search by content text with a grain_type filter. Both approaches work with the standard /recall endpoint.

Full-text search runs against the content field through BM25 ranking. When you filter by grain_type: "event", only Event grains are considered, which speeds up retrieval in databases with mixed grain types. Namespace filtering narrows results further — querying namespace: "session-42" with grain_type: "event" returns only that session’s events.

On the CLI, the --temporal flag accepts human-readable durations like "last 7 days" or "last 1 hour" and translates them to valid_from/valid_to ranges. This is useful for quick debugging but the HTTP API requires explicit Unix timestamps.

# Full-text search across events
results = db.recall(query="onboarding", grain_type="event")

# All events in a namespace
results = db.recall(grain_type="event", namespace="session-42")
POST /api/memories/default/recall
Content-Type: application/json

{"query": "onboarding", "grain_type": "event", "limit": 20}
areev recall --query "onboarding" --grain-type event --temporal "last 7 days"

When should I use Event vs. Action?

Use Event for things that happened passively or externally — incoming messages, system notifications, user behavior. Use Action for operations your agent actively performed, where you need to track tool name, input, output, error status, and duration.

An Event says “this happened.” An Action says “I did this, here is what I called and what came back.” If you only have a free-text description with no structured tool metadata, Event is the right choice. If you have a tool name and want to record the input/output contract, use Action.

A common pattern is to store an Event for the trigger (“user asked about weather”) and an Action for the response (“called web_search, got 72F sunny”). Link them with the related_to common field for full traceability.

  • Grain Types: Overview of all 10 OMS grain types and shared fields
  • Action: For agent-initiated operations with tool tracking
  • Observation: For structured perceptions with observer metadata
  • State: For point-in-time snapshots rather than occurrences