Expand description
rig-ecs, the kernel of the rig coding agent: agents, their turns and
their calls are Bevy entities, and the calls run on Bevy’s task pools.
Every call goes through one effect dispatch path, recorded as it settles
(effects); plugins register the tools. The kernel saves every change
of an agent’s Conversation to the
session_log::SessionStore the app inserts. Time is Bevy’s: a retried
model call waits on a delayed command, and plugins that animate or poll
run on on_real_timer, not on threads of their own.
The kernel depends on no view and no file system: the app fills in what
it needs, such as the store (any rig_memory::Store) and the
model::Models.
use rig_ecs::session_log::SessionStore;
use rig_ecs::prelude::*;
use rig_memory::MemoryStore;
let mut app = App::new();
app.insert_resource(SessionStore::new(MemoryStore::default()))
.add_plugins((AgentPlugin, SessionLogPlugin));Modules§
- agent
- The agent entity: its components, the calls it owns, and the requests a view sends it.
- effects
- The one dispatch path. Every effect entity (
stage), a model call, a tool call or a plugin’s effect, runs throughEffectsunder its effect id, recorded in the kernel’s ownRecordBuffer, and its record is written as aEffectRecordedwhen it settles. A plugin that keeps an effect log reads those, and continues the ids of the log it appends to withEffects::continue_after. - fork
- Forking an agent:
ForkAgentmakes a new agent in the same session whose log is a copy of another’s up to a turn boundary, so it goes on from there by itself, a compaction made before the cut can be undone in it, and its requests share the source’s prompt cache. - inbox
- Messages to agents. A message, whoever sends it (the user typing, an
agent reporting, a plugin), is an effect entity: an
IncomingForAgentthe agent, spawned byDeliveror by hand, which plugins edit in Prepare and take over in Gate by answering it. Each carries itsAuthor, kept with the conversation and its log; text that is not the user’s own goes to the model headed by a line naming its sender. Each message is its own entry: nothing merges into the message before. - model
- An agent’s model: the catalog model it chose, the reasoning setting it
sends, and how the choice is connected. The catalog and how its models
are reached are rig-core’s
Connector. - prelude
- What a plugin needs: Bevy’s app, ECS, reflection and time preludes (with
the time run conditions and
Disabled), the kernel’s components, requests and stages, the tool registry, rig-core’s conversation types and rig-memory’s store.Messageis Bevy’s message trait, a conversation’s message ismessage::Message, andConversationis the agent’s component. - prompt
- The system prompt, put together for each model call from two parts:
the agent’s own
SystemPromptand thePromptSections, the app’s and the agent’s own (SectionOf). Nothing in it depends on the turn, so it stays the same from call to call and the provider’s prompt cache keeps it. A section whose text changes costs the whole conversation’s cache once per change, so what changes goes in a message instead (DeliveryMode::Inform); a section that changes rarely sorts before one that changes more often. A request carries it in parts, rig-core’sSystemPrompt(ModelRequest::prompt), until Start sends it as one system message. - restore
- Restoring a session from its agent logs at startup, then one reconcile
pass that settles what a crash or a restart left half done, with
ordinary records, so the next restore finds nothing left to fix. The
session is read as
open_sessionreads it: strictly, refused whole before anything is written when it cannot be read, a torn last line set aside; a retired agent and the agents it spawned are not restored. - retry
- What to do about a failed model call: wait and send it again after a transient failure, honouring the wait the provider asked for; recover from a request that outgrew the model’s context window; or give up.
- session_
log - The session log in the app. Each agent’s log, in the session’s
SessionStore, gets every change of the agent’sConversationand of itsReflectSavedcomponents, such as its model, reasoning setting, system prompt, tool access and last usage. The format, its writer and its readers are rig-memory’s. - stage
- The stages every effect moves through within a frame. An effect is an
entity whose components are its request and its outcome, such as an
EffectRequestand, once answered, anOutcome; generic components say how far it got. Each run of theAgentPassschedule goes through theStagesets in order, and the loop inUpdate(AgentLoop) runs it again until nothing moved, so an effect spawned, answered or released goes as far as it can in that frame. - tasks
- Work that runs off the main thread: a
Runningtask on an entity becomes aDonecomponent when it finishes, through onepoll_taskssystem, so observers of that component carry on; on an effect, such as an open tool call, it becomes the effect’sOutcomeinStage::Arrive. A long-lived source, such as a socket or a thread’s channel, is aRunning::streamwhose every item becomes aDoneon the entity, in order. Each finished task and each item also callsWake, so a loop that sleeps while nothing happens runs a frame for it. - tools
- The tool registry and tool calls. A tool is an entity holding its
definition and its default
Footprint, and, for an ordinary tool, its effect handler; plugins add tools withAppToolsExt::add_tool. A tool call is an effect entity with aToolRequest. An ordinary tool’s handler answers it; an open tool’s call triggersToolCalledand stays open until any system decides it (Decision). - turn
- The turn loop. A user message spawns a turn entity,
TurnOfits agent; its model and tool calls are effect entitiesCallOfthe turn.
Structs§
- Agent
Plugin - The kernel: agents, their turn loop, effects and the tool registry, and
the saving of every conversation change (announced as
session_log::ConversationChanged). - Save
Systems - The systems in
Lastthat queue what the frame changed for the session log: every conversation changed and everyReflectSavedvalue, afterStopTurnsOnExitand beforeWriteLogs. A plugin’sLastsystem that changes saved state goes.before(SaveSystems): one after it is saved a frame late, and on the exit frame never. - Stop
Turns OnExit - The system in
Last, on exit, that stops the running turns and leaves them for the restart, unended; beforeWriteLogs, both in Bevy’sOnAppExitSystems. - Write
Logs - The systems in
Lastthat write the frame’s log records to thesession_log::SessionStore, and those a plugin adds to write its own logs, such as the effect log: such a system says.in_set(WriteLogs)and nothing else. It runs afterSaveSystemsand the turns stopped on exit, so it writes what they left too. A failed write stops the logging and sends aNoticehere, at the end of the frame, which a system that runs before it reads the next frame and, on the exit frame, never: on exit, readSessionLog::failureor go.after(WriteLogs).