Architecture
Raw is a single local program with several front ends: the terminal, a browser dashboard, and ACP for editors and parent agents. All of them share one agent loop, one tool registry, and one session store.
Components
Section titled “Components”| Component | Responsibility |
|---|---|
| Config loader | Reads the config file, resolves one agent per session, and validates every field. |
| Provider adapters | Talk to each model service through its official SDK, and stream results into one common event shape. |
| Agent loop | Owns the transcript and the step count. Runs one turn at a time per session. |
| Tool registry | Validates arguments, decides which tools are exposed, applies rules, and runs approved handlers. |
| Skills and hooks | Load selected skill folders and run selected hook commands at events. |
| MCP client | Connects to the servers an agent selects, and adds only the selected tools to the registry. |
| Session store | Saves conversations, display history, and model context in a private local database. |
| Terminal UI | Renders events. It does not run the agent loop. |
| ACP server | Exposes sessions over stdio or a local WebSocket. |
| Dashboard server | Serves the browser app and its local API. |
The CLI renders events from the loop, but it never runs the loop itself. The dashboard and ACP use the same session operations.
What the model receives
Section titled “What the model receives”Each inference request contains only:
- One system prompt.
- The JSON schemas of the tools the agent selected.
- The conversation so far: user messages, assistant messages, and tool results.
Configuration, provider lists, logs, approval text, and usage counters are kept on the host side. Tool schemas count toward the context, and Raw measures them together with the prompt.
Committed history is not rewritten between ordinary turns. New messages are appended to it. This keeps the request prefix stable, so provider-side caches can be reused. Cache reuse depends on the provider and is never guaranteed.
The turn
Section titled “The turn”A turn starts with one user message and makes at most max_steps inference requests.
- The loop sends the request and streams the assistant’s text as it arrives.
- A completed assistant message is committed only after its stream finishes.
- If the message contains tool calls, the whole batch is committed first. Then the calls run in the order the model listed them.
- Each call gets a result, including errors for unknown tools, invalid arguments, denials, and cancellations. Results are appended before the next request.
- The loop stops when the model answers without a tool call, when a limit is reached, or when the turn is cancelled.
If the last permitted request asks for a tool, the turn ends with max_steps before the tool runs. A cancelled turn keeps the completed results and records a cancelled result for each unfinished call, so the transcript stays valid.
Each run produces one terminal event. Renderers receive detached copies of event data, so a renderer cannot change the arguments or results that were authorized.
Permissions
Section titled “Permissions”Raw runs with the full permissions of the operating-system account that started it. The session’s working directory resolves relative paths. It does not limit access to absolute paths.
Tool rules and approval decide which registered handlers Raw dispatches. They are not an operating-system sandbox, and an allowed bash call can do anything your shell can do.
Sessions and storage
Section titled “Sessions and storage”Sessions are stored in a private SQLite database in the user’s state directory. The database keeps two things separately:
- Display history: what the user saw, in order. Paged with opaque cursors.
- Model context: the messages the next request will include. Compaction replaces older parts of this with a summary, while the display history stays available.
Each session has a stable ID that the CLI, dashboard, and ACP all use. A session can be open in one writer at a time. Another process can read it but cannot write to it until the writer releases it.
Sessions expire after a set number of days without committed conversation activity. Reading or listing a session does not renew it. See Configuration.
Runtime changes
Section titled “Runtime changes”A session can be resumed after you change its config, tools, or skills. Raw compares the new definitions with the ones the session last used.
- If the model-facing tool definitions changed, the prompt cache key changes once, and the conversation continues with the new tools.
- If only a skill’s text changed, the cache key stays the same. If the model had already seen the old text, Raw adds a notice asking it to reload the skill.
- Committed history is never rewritten to match a change.
Variables
Section titled “Variables”Variable definitions are part of the config. Values are read when they are needed, and they are cached only in memory for the length of one runtime. Values are never written to the session database. See Variables.
Packages
Section titled “Packages”Installing a package writes an alias to a per-config index and stores the package’s files under a content-addressed directory in the user’s data directory. Loading a config resolves only the agent that was selected and the package exports it refers to. Packages do not run code when they are installed or inspected.
Dashboard
Section titled “Dashboard”The dashboard server listens on 127.0.0.1 and requires a per-process token on every API request. It uses the same session operations as the CLI and ACP, so a conversation started in one can be resumed in another. Browser preferences are kept separate from the config file. See Dashboard API.
Related
Section titled “Related”- Tool contract describes the policy and hook contracts that the registry uses.
- Sessions and context and context and compaction describe these behaviors from a user’s point of view.