Grain Types

What are grain types?

Every memory stored in the Areev context database is classified as one of 10 grain types defined by the Open Memory Schema (OMS) 1.2. The grain type determines which fields a memory carries, how it is indexed, and how AI agent memory recall surfaces it in queries.

Grain types enforce structure at the storage layer. When you write a grain, Areev validates the type-specific fields, serializes the grain into the .mg binary format with a single-byte type header, and indexes it for retrieval. When you recall grains, the type constrains which fields are available for filtering and how the text representation is built for BM25 and vector search. This structure is what separates an autonomous memory system from an untyped key-value store: each grain carries semantic meaning that agents can reason over.

The 10 types cover the full lifecycle of agent cognition — from perceiving the world (Observation) to forming knowledge (Belief), making decisions (Reasoning, Consensus), taking action (Action, Workflow), tracking objectives (Goal), managing state (State, Event), and handling compliance (Consent). The first seven types originated in OMS 1.1 under different names; Reasoning, Consensus, and Consent were introduced in OMS 1.2.

ByteTypeSerialized NamePurpose
0x01BeliefbeliefStructured knowledge triple (subject/relation/object)
0x02EventeventTimestamped occurrence or message
0x03StatestateAgent state snapshot or checkpoint
0x04WorkflowworkflowDirected-graph procedural plan (nodes + edges)
0x05ActionactionTool invocation or operation record
0x06ObservationobservationCognitive observer perception
0x07GoalgoalAgent objective with satisfaction criteria
0x08ReasoningreasoningInference chain and thought audit trail
0x09ConsensusconsensusMulti-agent agreement record
0x0AConsentconsentDID-scoped permission grant or withdrawal

How do I add a grain to the context database?

Pass the grain_type string and the type-specific fields to the appropriate endpoint. The /add endpoint is reserved for Belief grains and indexes subject/relation/object in the hexastore for graph traversal. The /batch-add endpoint accepts any grain type and supports writing multiple grains in a single request.

When using the Python SDK, db.add() accepts the grain type as its first argument and a dict of type-specific fields as its second argument. The method returns a content-address hash that uniquely identifies the grain. For HTTP, Belief grains use /add with a flat JSON body; all other types use /batch-add with a grains array where each entry specifies grain_type and fields.

Areev validates fields against the OMS 1.2 schema before writing. Required fields that are missing cause a 400 error. Optional fields default to null or their documented defaults (for example, goal_state defaults to "active").

import areev

db = areev.open("./data")

# Belief -- triple-indexed in the hexastore
db.add("belief", {"subject": "john", "relation": "likes", "object": "coffee"})

# Event -- free-text content
db.add("event", {"content": "User completed onboarding"})

# Action -- tool call with result
db.add("action", {"tool_name": "web_search", "input": {"q": "weather"}, "content": "72F sunny"})
POST /api/memories/default/add
Content-Type: application/json

{"subject": "john", "relation": "likes", "object": "coffee"}
POST /api/memories/default/batch-add
Content-Type: application/json

{
  "grains": [
    {"grain_type": "event", "fields": {"content": "User completed onboarding"}},
    {"grain_type": "action", "fields": {"tool_name": "web_search", "content": "72F sunny"}}
  ]
}

Which grain type should I use?

Choose based on what the memory represents, not how you plan to query it.

  • Storing knowledge claims (who/what/how relationships) — use Belief. Its subject/relation/object triple is indexed in the hexastore for graph queries.
  • Recording things that happened (messages, logs, conversations) — use Event. Events are optimized for temporal queries.
  • Saving agent checkpoints (session state, config snapshots) — use State. States carry arbitrary JSON and support supersession for updates.
  • Encoding procedures (runbooks, multi-step plans) — use Workflow. Workflows are directed graphs with nodes, edges, optional bindings, retries, and a trigger.
  • Logging tool calls (API calls, code execution, computer use) — use Action. Actions track tool name, input, output, errors, and duration.
  • Capturing perceptions (sensor data, LLM observations, multi-agent views) — use Observation. Observations track observer identity and scope.
  • Tracking objectives (tasks, targets, milestones) — use Goal. Goals have state transitions (active/satisfied/failed/suspended) and priority levels.
  • Preserving inference chains (decision audit trails, thought traces) — use Reasoning. Reasoning grains store premises, conclusions, and alternatives.
  • Recording multi-agent decisions (votes, quorum outcomes) — use Consensus. Consensus tracks participating observers, agreement/dissent counts, and thresholds.
  • Managing permissions (data-subject consent, access grants) — use Consent. Consent grains are DID-scoped and purpose-bounded for compliance.

What fields do all grains share?

Every grain type inherits a set of common fields from GrainCommon in addition to its type-specific fields. These common fields control indexing, access, temporal validity, and inter-grain relationships across the entire AI memory system.

The confidence field (0.0 to 1.0) lets agents express certainty. The namespace and tags fields scope queries and organize grains into logical groups. The superseded_by field and supersession mechanism support immutable updates — rather than modifying a grain in place, you create a new version and link the old grain to it. Bi-temporal fields (valid_from, valid_to, temporal_type) let you model business time separately from storage time.

Fields like related_to and content_refs create explicit links between grains and to external resources. The verification_status field tracks whether a grain has been independently verified, contested, or retracted. The invalidation_policy field protects regulated grains from premature deletion.

FieldTypeDefaultDescription
namespacestringnullLogical grouping for scoped queries
user_idstringnullOwner user ID for access control and erasure
tagsstring[][]Searchable labels
confidencefloat1.0Trust score from 0.0 to 1.0
source_typestringnullOrigin indicator (e.g., "user", "agent", "system")
importancefloatnullPriority weight for recall ranking
temporal_typestringnullBi-temporal model: "state", "event", or "interval"
valid_fromintnullStart of business validity (Unix timestamp)
valid_tointnullEnd of business validity (Unix timestamp)
verification_statusstringnull"unverified", "verified", "contested", or "retracted"
embedding_textstringnullCustom text override for vector embedding (max 8192 bytes)
related_toobject[][]Links to other grains by hash with relation type and weight
content_refsobject[][]References to external content (URIs, MIME types, checksums)
superseded_bystringnullHash of the grain that replaced this one
invalidation_policyobjectnullProtection rules for regulated grains

How did grain type names change from OMS 1.1 to 1.2?

OMS 1.2 renamed four grain types from OMS 1.1 to better reflect their semantics. The byte codes remain the same, and Areev accepts both old and new names during a transition period.

The renames are: Fact became Belief (0x01), Episode became Event (0x02), Checkpoint became State (0x03), and ToolCall became Action (0x05). The Action grain also changed three field names: arguments became input, result became content, and success became is_error (with inverted boolean logic — success: true maps to is_error: false). If you have existing code using OMS 1.1 names, update to the new names to avoid deprecation warnings.

  • Belief: Structured knowledge triples indexed in the hexastore
  • Event: Timestamped occurrences and messages
  • State: Agent state snapshots with supersession
  • Action: Tool invocations with input, output, and error tracking