Skip to content

Primitives Overview

Grain defines 10 core primitives. Companion elements like <result>, <progress>, <warning>, <action>, and <option> round out the language contract.


The 10 Core Primitives

PrimitivePurpose
StreamReal-time text streaming
ThinkAI reasoning display
ToolFunction/tool execution
ArtifactCode, images, documents
InputUser input collection
ContextFiles, URLs, memory
StateGlobal AI status
ErrorFailure handling
ApproveHuman-in-the-loop
BranchConversation forks

Composition

Primitives compose into complex interfaces:

grain
<message role="assistant">
  <think model="chain-of-thought" visible="false">
    User asks about weather. I should call the weather tool.
  </think>
  <stream>Let me check...</stream>
  <tool name="get_weather" status="running" />
</message>

<tool name="get_weather" status="complete">
  <result temperature="28" condition="sunny" />
</tool>

<message role="assistant">
  <stream>28°C and sunny!</stream>
</message>

This is the core Grain idea: a model or agent can move between reasoning, streaming, tool execution, and final response without leaving the same document contract.


State Machines

Every primitive has explicit states:

STREAM:  IDLE → GENERATING → COMPLETE

                   PAUSED

TOOL:    PENDING → RUNNING → COMPLETE

                   ERROR

APPROVE: PENDING → SHOWING → APPROVED/DENIED

Events

Each primitive emits events:

  • stream.start, stream.chunk, stream.complete
  • tool.start, tool.progress, tool.complete, tool.error
  • think.reveal, think.hide
  • approve.request, approve.approve, approve.deny

Companion Elements

Core primitives often carry smaller semantic companions:

  • <result> for structured tool output
  • <progress> for long-running work
  • <warning> for user-facing cautions
  • <option> for approval choices
  • <suggestion> for input affordances

Extending

Add custom primitives:

javascript
adapter.registerPrimitive('my-chart', {
  render: (props) => `<div class="my-chart">...</div>`
});

When extending Grain, keep the public contract narrow. The documented primitives should stay stable while custom behavior lives behind explicit extensions.


Next

Released under the MIT License.