# Agents ## Overview An **agent** is an AI participant in chats, or an independent service invoked through prompts and actions. Agents are owned by a user, belong to a chat as members, and come in different **kinds** — each kind backed by a Python class implementing its behavior. Agent instances are created and destroyed constantly. Everything durable (config, resources, chat membership) lives in the database or in resources, not in the agent object itself. ## Agent Kinds Every agent has a `kind` matching the `identifier` of a registered agent class. The class defines: * **`identifier`** — the kind name used at creation. * **`description`** — shown when listing agent kinds. * **`schema_fields`** — the agent's configuration fields (name, type, default). Values are stored in the agent's `data` and editable through the standard agent update path. The Expert agent, for example, exposes `system_prompt`, `model`, `temperature`, and `repetition_penalty`. The server resolves the kind's class to build a live **control object** (`get_agent_control`) wrapping the agent's config and resources. Prompting and actions always go through a control object. ## Creation & Identity * Agents are created with a name, optional `agentname` (unique handle), description, picture, kind, and config data. * Persistent agents get a **main chat** automatically (created if not provided) and are added to it as a member. * Agents can also be created **temporary**: they live only in memory, and their main chat must be a temporary chat. Temporary agents appear in listings alongside persistent ones. * Agents are addressed by id, or resolved from their `agentname`. ## Resources & Tools Agents are extended through **resources**: key–value records with a `kind`, attached to the agent. The important kind is `tools`, which turns a resource into a callable tool for the agent: * **Native tools** reference a tool class registered in the app (e.g. Calc). The resource key becomes the tool's name, so one tool can be exposed under multiple names. * **Remote tools** are not stored as resources. Instead, a chat thread can carry `remote` resources declaring which connected remotes the agent may use (see [Remotes](remotes.md)). At run time those remotes are expanded into tools. ## Agent Runs All agent activity happens inside an **AgentRun** — an envelope holding the run input (instruction, input, messages, tools), events, and outputs. Runs are always temporary, in-memory objects. * **Input**: a plain dict (instruction, messages, tools, chat/thread ids, remotes). Tools can be added to the run before or during execution. * **Events**: the run records a named event log. Listeners can subscribe at any time; past events are replayed so late subscribers see the full history. Events are also broadcast to websocket clients as `run-event`. * **Output streams**: `output` and `reasoning` are streams that carry content incrementally; run events carry additional streams (e.g. tool calls). Streams close when the run finishes. * **Cancellation**: runs can be cancelled by id. Cancellation closes the streams, marks the run done, and stops the underlying task where possible. Runs are created and closed by the agent itself, or driven from the outside (create/cancel/list run endpoints). ## Two Entry Points Agents are driven in two ways: 1. **Prompting** (`prompt`): a one-shot instruction (with optional structured input and options). The run's output stream is returned to the caller — suitable for non-chat use of an agent. 2. **Chat messages** (`received_message`): when a chat message arrives, member agents are notified. The agent builds a run from the message's thread: thread messages become LLM messages (roles derived from senders), remote resources become tool remotes, and the run's output/reasoning are streamed back into the chat as new messages in the same thread. ## The Expert Agent The Expert agent (`expert` kind) is the main conversational agent: a customizable system prompt plus an inference loop. * Config: system prompt, model id, temperature, repetition penalty. * Tool resolution: if the run carries tools, they are used as-is. Otherwise the agent falls back to its own resource tools and remote tools. * Loop: inference is called with the message history and tools. When the model emits tool calls, the agent executes them (including remote tools), appends the results, and repeats inference. When the model produces final content without tool calls, the loop ends and the run closes. * Everything it does is streamed through the run's events, so chat messages appear incrementally as they're generated. ## Frontend: the agent view The agent page is the management console over these concepts: the kind description and identity with inline editing, the schema-driven configuration form (fields can be toggled), a **prompt console** with optional instruction/input stages and a history of past prompts and outputs, and editing of tools and resources as JSON entries. Live run observation and cancellation happen in the chat view instead, where runs surface as messages. ### Backend and frontend On the backend, agents are **kinds, controls and runs**: the App owns the registries and persistence, instantiates controls, and orchestrates runs with events and streams. On the frontend, agents are **management and prompting**: the view edits identity, configuration, tools and resources, and fires one-off prompts.