docs: document agent, chat, and api endpoints
This commit is contained in:
1 parent
563f1871d2
commit
c22ac6d3e2
3 files changed
+294
No files matched your search
@@ -0,0 +1,68 @@
|
|||||||
|
# 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.
|
||||||
+156
@@ -0,0 +1,156 @@
|
|||||||
|
# API Documentation
|
||||||
|
|
||||||
|
This document documents all WebSocket actions and HTTP paths used by the WebSocket server.
|
||||||
|
|
||||||
|
## HTTP Paths
|
||||||
|
|
||||||
|
- `/` - Serves the frontend `index.html`
|
||||||
|
- `/user`, `/models`, `/remotes`, `/runs`, `/chat`, `/agent` - SPA routes
|
||||||
|
- `/chat/<path:subpath>`, `/agent/<path:subpath>` - SPA routes (subpaths handled by Vue router)
|
||||||
|
- `/<path:path>` - Static file routes
|
||||||
|
- `POST /user/login` - User login (supports token or username/password auth)
|
||||||
|
- `POST /user/signup` - User signup (creates default data after registration)
|
||||||
|
- `POST /api/openai/v1/chat/completions` - OpenAI-compatible chat completion endpoint
|
||||||
|
- `GET /api/openai/v1/models` - OpenAI-compatible models list endpoint
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## WebSocket Actions (Client → Server)
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
- `ping` - Heartbeat; server responds with `"pong"`
|
||||||
|
|
||||||
|
### Agent Management
|
||||||
|
|
||||||
|
- `create-agent` - Creates a new agent
|
||||||
|
- Payload: `name`, `agentname` (optional), `description` (optional), `picture` (optional), `kind`, `data` (optional), `temporary` (optional)
|
||||||
|
- Response: `agentId`, `nonce`
|
||||||
|
|
||||||
|
- `update-agent` - Updates an existing agent
|
||||||
|
- Payload: `agentId` or `agentname`, `name` (optional), `agentname` (optional), `description` (optional), `picture` (optional), `data` (optional)
|
||||||
|
- Response: `agentId`, `nonce`
|
||||||
|
|
||||||
|
- `get-agent-config-fields` - Returns configuration schema fields for an agent
|
||||||
|
- Payload: `agentId` or `agentname`
|
||||||
|
- Response: `fields`, `nonce`
|
||||||
|
|
||||||
|
- `get-agent-kinds` - Returns all registered agent kinds
|
||||||
|
- Response: `kinds`, `nonce`
|
||||||
|
|
||||||
|
- `get-agent-kind-info` - Returns details for a specific agent kind
|
||||||
|
- Payload: `kind`
|
||||||
|
- Response: `info`, `nonce`
|
||||||
|
|
||||||
|
- `get-agents` - Returns all agents for the authenticated user
|
||||||
|
- Response: `agents`, `nonce`
|
||||||
|
|
||||||
|
- `get-agent-resources` - Returns agent resources
|
||||||
|
- Payload: `agentId` or `agentname`, `kind` (optional), `key` (optional)
|
||||||
|
- Response: `resources` list with `kind`, `key`, `value`
|
||||||
|
|
||||||
|
- `save-agent-resource` - Saves an agent resource
|
||||||
|
- Payload: `agentId` or `agentname`, `kind`, `key`, `value`
|
||||||
|
- Response: `nonce`
|
||||||
|
|
||||||
|
- `get-agent-runs` - Returns agent runs (optionally filtered by agent or user)
|
||||||
|
- Payload: `agentId` or `agentname` (optional), `runId` (optional)
|
||||||
|
- Response: `runs`, `nonce`
|
||||||
|
|
||||||
|
- `cancel-agent-run` - Cancels an agent run
|
||||||
|
- Payload: `runId`
|
||||||
|
|
||||||
|
- `send-agent-prompt` - Sends a prompt to an agent
|
||||||
|
- Payload: `agentId` or `agentname`, `instruction` or `input`, `options` (optional), `stream` (optional)
|
||||||
|
- Response: `response` (stream ID if streaming, final content otherwise), `nonce`
|
||||||
|
|
||||||
|
### Model Management
|
||||||
|
|
||||||
|
- `get-models` - Returns all available models
|
||||||
|
- Response: `models` list with `id`, `name`, `value`, `kind`, `nonce`
|
||||||
|
|
||||||
|
- `save-model` - Creates or deletes a model
|
||||||
|
- Payload: `modelId` (optional), `name`, `kind`, `value`
|
||||||
|
- Response: `message`, `modelId` or `message` with deletion, `nonce`
|
||||||
|
|
||||||
|
### Remote Management
|
||||||
|
|
||||||
|
- `remote-list` - Lists remotes for the authenticated user
|
||||||
|
- Response: `remotes`, `nonce`
|
||||||
|
|
||||||
|
- `remote-connect` - Connects a new remote (served by this session)
|
||||||
|
- Payload: `remotename`, `functions` array of `{name, description, parameters}`
|
||||||
|
- Response: `remotename`, `nonce` (or error)
|
||||||
|
|
||||||
|
- `remote-disconnect` - Disconnects a remote
|
||||||
|
- Payload: `remotename`
|
||||||
|
- Response: `remotename`, `nonce` (or error if not found)
|
||||||
|
|
||||||
|
- `remote-call` - Invokes a function on a connected remote
|
||||||
|
- Payload: `remotename`, `function`, `args`
|
||||||
|
- Response: `result` or `error`, `nonce`
|
||||||
|
|
||||||
|
### Chat Management
|
||||||
|
|
||||||
|
- `create-chat` - Creates a new chat
|
||||||
|
- Payload: `name`, `description` (optional), `picture` (optional), `members` (optional array of agent IDs), `temporary` (optional)
|
||||||
|
- Response: `chatId`, `nonce`
|
||||||
|
|
||||||
|
- `get-chats` - Returns all chats for the authenticated user
|
||||||
|
- Response: `chats`, `nonce`
|
||||||
|
|
||||||
|
- `delete-chat` - Deletes a chat
|
||||||
|
- Payload: `chatId`
|
||||||
|
- Response: `chatId`, `nonce`
|
||||||
|
|
||||||
|
- `get-chat-messages` - Returns messages for a chat (paginated)
|
||||||
|
- Payload: `chatId`, `earliestIndex` (optional, defaults to 0)
|
||||||
|
- Response: `messages`, `nonce`
|
||||||
|
|
||||||
|
- `send-chat-message` - Sends a chat message
|
||||||
|
- Payload: `chatId`, `threadId` (optional), `content`, `kind` (optional), `subkind` (optional), `format` (optional)
|
||||||
|
- Response: `messageId`, `nonce`
|
||||||
|
|
||||||
|
- `update-chat-message` - Updates a chat message
|
||||||
|
- Payload: `messageId`, `content`, `kind` (optional), `subkind` (optional), `format` (optional)
|
||||||
|
- Response: `messageId`, `nonce`
|
||||||
|
|
||||||
|
- `create-chat-thread` - Creates a new chat thread
|
||||||
|
- Payload: `chatId`, `name` (optional)
|
||||||
|
- Response: `threadId`, `nonce`
|
||||||
|
|
||||||
|
### Streaming
|
||||||
|
|
||||||
|
- `read-stream` - Reads the content of a stream incrementally
|
||||||
|
- Payload: `streamId`
|
||||||
|
- Response: `data` (chunks), `eof` (boolean), `fullData` (when eof is true), `nonce`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## WebSocket Actions (Server → Client)
|
||||||
|
|
||||||
|
### Agent Events
|
||||||
|
|
||||||
|
- `run-event` - Agent run event (used during chat messages and prompts)
|
||||||
|
- Payload: event data, includes output, reasoning, tool calls, done state
|
||||||
|
|
||||||
|
### Remote Events
|
||||||
|
|
||||||
|
- `remote-call-result` - Result of a remote function call
|
||||||
|
- Payload: `requestId`, `result`, `error`
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
- Server sends `"message": "authentication successful"` after successful authentication
|
||||||
|
|
||||||
|
### User Notifications
|
||||||
|
|
||||||
|
- `message` - Generic message type for various responses
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Response Fields
|
||||||
|
|
||||||
|
- `nonce` - Optional request identifier for matching responses
|
||||||
|
- `error` - Optional error message when an operation fails
|
||||||
|
- `message` - Confirmation message for successful operations
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Chats
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
A **chat** is a conversation container owned by a user. Agents become chat members, receive messages, and can reply in threads. Every message a user sees belongs to a chat.
|
||||||
|
|
||||||
|
Chats are either **persistent** (stored in the database) or **temporary** (in-memory only, useful for quick, unsaved conversations). Both kinds share the same features and appear together in listings.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
A chat contains:
|
||||||
|
|
||||||
|
* **Messages** — the conversation content.
|
||||||
|
* **Threads** — messages can be grouped into named threads; messages without a thread go to the chat's default thread.
|
||||||
|
* **Memberships** — which agents are in the chat. Every agent is created with a **main chat** it belongs to.
|
||||||
|
|
||||||
|
## Messages
|
||||||
|
|
||||||
|
Each message carries:
|
||||||
|
|
||||||
|
* `sender` — `'user'` or an agent id.
|
||||||
|
* `kind` — the message class: `message` (normal content), `log` (agent internals like reasoning), `note` (annotations), or `resource` (declarations such as remotes; not shown to agents).
|
||||||
|
* `subkind` — a refinement of the kind (e.g. `reasoning`, `remote`).
|
||||||
|
* `format` — content format hint.
|
||||||
|
* `threadId` — the thread the message belongs to.
|
||||||
|
|
||||||
|
Message content may be a **stream** rather than a final value: the message is stored immediately with a stream reference and updated in place when the stream finishes. This is how agent replies appear progressively.
|
||||||
|
|
||||||
|
## Delivery
|
||||||
|
|
||||||
|
When a message is sent to a chat:
|
||||||
|
|
||||||
|
* The chat's owner is notified over their websocket connections (as an update when a streamed message settles).
|
||||||
|
* Every member agent is notified, except the sender itself. The agent then builds a run from the message's thread and can stream a reply into the same thread.
|
||||||
|
* `resource` messages are not delivered to agents — they are declarations, not conversation.
|
||||||
|
|
||||||
|
## Threads
|
||||||
|
|
||||||
|
Threads are lightweight sub-conversations inside a chat:
|
||||||
|
|
||||||
|
* Messages with no thread id belong to the chat's implicit **default thread**.
|
||||||
|
* Named threads can be created on demand; new messages open new threads implicitly.
|
||||||
|
* `note` and `resource` messages are attached to their thread separately from the main message list, so notes and remote declarations travel with a thread without polluting the conversation.
|
||||||
|
|
||||||
|
## Reading Chats
|
||||||
|
|
||||||
|
The **ChatView** is the read-side view of a chat in the backend, used both by agents (to build their message history) and by tooling:
|
||||||
|
|
||||||
|
* Loads the chat's basic data plus the most recent page of messages (`MESSAGE_PAGE_SIZE`), paging further back on demand — messages are ordered by id, which is more robust than timestamps.
|
||||||
|
* Groups messages into threads, keeping messages, notes, and resources separate per thread.
|
||||||
|
* Tracks the **current thread** (the most recently active one) and provides a debug dump of the full structure.
|
||||||
|
|
||||||
|
## Lifecycle
|
||||||
|
|
||||||
|
* Chats are created with a name, description, picture, and an optional list of member agents.
|
||||||
|
* Agents can be added to existing chats at any time.
|
||||||
|
* Deleting a chat removes its memberships.
|
||||||
|
|
||||||
|
## Frontend: the chat view
|
||||||
|
|
||||||
|
The chat page is the live surface of these concepts:
|
||||||
|
|
||||||
|
- **Messages** render with sender names resolved from the agent registry; new messages arrive over websockets, streamed content updates in place, and the user's own messages appear optimistically until the broadcast confirms them.
|
||||||
|
- **Threads** are UI-first: "New Thread" is a local state, and the thread is only created upstream once a message is actually sent into it. Exactly one thread is open at a time — the active one — while all others collapse into preview headers; opening a preview makes that thread active. The last thread is only continued automatically while it is fresh (ten minutes), otherwise the chat starts in "New Thread" state.
|
||||||
|
- **Composing** supports note mode, editing an existing message, and attaching a connected remote to the current thread as a resource.
|
||||||
|
- **Runs** are tracked per message, so an in-flight agent reply can be cancelled from the chat.
|
||||||
|
|
||||||
|
### Backend and frontend
|
||||||
|
|
||||||
|
On the backend, chats are **storage and routing**: the App owns chat, thread and message persistence, membership, and the notification fan-out to users and agents. On the frontend, chats are **presentation and composing**: thread UX, live updates, optimistic sending, notes and edits.
|
||||||
Reference in new issue
Block a user