Skip to content

Commit 3358463

Browse files
committed
2 parents 07a8fc1 + 8d0deac commit 3358463

9 files changed

Lines changed: 473 additions & 12 deletions

File tree

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ A **built-in web console** is served at `/` from the same HTTP process — no ex
2323

2424
## Documentation
2525

26-
➡️ **[Full documentation → agentchatbus.readthedocs.io](https://agentchatbus.readthedocs.io)**
26+
<p align="center"><a href="https://agentchatbus.readthedocs.io" target="_blank" rel="noopener"><b>Full documentation → agentchatbus.readthedocs.io</b></a></p>
2727

2828
---
2929

@@ -42,7 +42,15 @@ A **built-in web console** is served at `/` from the same HTTP process — no ex
4242
| Rate limiting | Per-author message rate limiting (configurable, pluggable) |
4343
| Thread timeout | Auto-close inactive threads after N minutes (optional) |
4444
| Image attachments | Support for attaching images to messages via metadata |
45-
| Zero external dependencies | SQLite only — no Redis, no Kafka, no Docker required |
45+
| No external infrastructure | SQLite only — no Redis, no Kafka, no Docker required |
46+
| `bus_connect` (one-step) | Register an agent and join/create a thread in a single call |
47+
| Message editing | Edit messages with full version history (append-only edit log) |
48+
| Message reactions | Annotate messages with free-form labels (agree, disagree, important…) |
49+
| Full-text search | FTS5-powered search across all messages with relevance ranking |
50+
| Thread templates | Reusable presets (system prompt + metadata) for thread creation |
51+
| Admin coordinator | Automatic deadlock detection and human-confirmation admin loop |
52+
| Reply-to threading | Explicit message threading with `reply_to_msg_id` |
53+
| Agent skills (A2A) | Structured capability declarations per agent (A2A `AgentCard`-compatible) |
4654

4755
---
4856

docs/development/structure.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ AgentChatBus/
2525
│ ├── content_filter.py # Secret/credential detection for message content
2626
│ ├── db/
2727
│ │ ├── database.py # Async SQLite connection + schema init + migrations
28-
│ │ ├── models.py # Dataclasses: Thread, Message, AgentInfo, Event, ThreadTemplate
28+
│ │ ├── models.py # Dataclasses: Thread, Message, AgentInfo, Event, ThreadTemplate, MessageEdit, Reaction, ThreadSettings
2929
│ │ └── crud.py # All database operations with rate limiting & sync
3030
│ ├── static/
3131
│ │ ├── index.html # Built-in web console
@@ -74,3 +74,20 @@ AgentChatBus/
7474
├── LICENSE # MIT License
7575
└── README.md
7676
```
77+
78+
---
79+
80+
## Data Models (`src/db/models.py`)
81+
82+
All models are plain Python dataclasses used across the DB, MCP, and API layers.
83+
84+
| Model | Description |
85+
|---|---|
86+
| `Thread` | A conversation thread with topic, status, system prompt, and optional template. |
87+
| `Message` | A single message in a thread with author, role, content, seq, priority, and edit metadata. |
88+
| `ThreadTemplate` | A reusable preset for thread creation (built-in or custom). |
89+
| `AgentInfo` | A registered agent with identity, capabilities, skills, heartbeat, and online status. |
90+
| `Event` | A transient notification row used for SSE fan-out. Consumed and deleted by the SSE pump. |
91+
| `MessageEdit` | One entry in the append-only edit history for a message. Stores `old_content`, `edited_by`, and `version`. |
92+
| `Reaction` | A reaction/annotation on a message (e.g. `"agree"`, `"disagree"`, `"important"`). `agent_id` is optional. |
93+
| `ThreadSettings` | Thread-level coordination settings: `auto_administrator_enabled`, `timeout_seconds`, admin identity tracking. |

docs/getting-started/config.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,20 @@ All settings are controlled by environment variables. The server falls back to s
88
|---|---|---|
99
| `AGENTCHATBUS_HOST` | `127.0.0.1` | Bind address. Use `0.0.0.0` to listen on all interfaces (less secure, use carefully). |
1010
| `AGENTCHATBUS_PORT` | `39765` | HTTP port. Change if it conflicts with another service. |
11-
| `AGENTCHATBUS_DB` | `data/bus.db` | Path to the SQLite database file. |
11+
| `AGENTCHATBUS_DB` | see below | Path to the SQLite database file. In source mode: `data/bus.db` (repo root). In installed package mode: `~/.agentchatbus/bus.db`. |
1212
| `AGENTCHATBUS_HEARTBEAT_TIMEOUT` | `30` | Seconds before an agent is marked offline after missing heartbeats. |
1313
| `AGENTCHATBUS_WAIT_TIMEOUT` | `300` | Max seconds `msg_wait` will block before returning an empty list. |
1414
| `AGENTCHATBUS_RELOAD` | `1` | Enable hot-reload for development (set to `0` to disable for stable clients). |
1515
| `AGENTCHATBUS_RATE_LIMIT` | `30` | Max messages per minute per author (set to `0` to disable rate limiting). |
1616
| `AGENTCHATBUS_THREAD_TIMEOUT` | `0` | Auto-close threads inactive for N minutes (set to `0` to disable). |
17+
| `AGENTCHATBUS_TIMEOUT_SWEEP_INTERVAL` | `60` | How often (in seconds) the thread-timeout sweep background task runs. |
1718
| `AGENTCHATBUS_EXPOSE_THREAD_RESOURCES` | `false` | Include per-thread resources in MCP resource list (can reduce clutter). |
1819
| `AGENTCHATBUS_ADMIN_TOKEN` | (none) | Admin token for server settings updates. Set this to enable `/api/settings` write access. |
1920
| `AGENTCHATBUS_DB_TIMEOUT` | `5` | Database operation timeout in seconds. Increase if you experience timeout errors on slow systems. |
21+
| `AGENTCHATBUS_REPLY_TOKEN_LEASE_SECONDS` | `3600` | How long (in seconds) a `reply_token` issued by `thread_create` or `msg_wait` remains valid. Default is 1 hour to accommodate typical LLM thinking time. |
22+
| `AGENTCHATBUS_SEQ_TOLERANCE` | `0` | Number of missed sequence numbers tolerated before `msg_post` returns a sync error. `0` means strict (no gaps allowed). |
23+
| `AGENTCHATBUS_SEQ_MISMATCH_MAX_MESSAGES` | `100` | Max number of unread messages tolerated before a seq-mismatch error is raised. |
24+
| `AGENTCHATBUS_CONTENT_FILTER_ENABLED` | `true` | When `true`, the server rejects messages containing secrets or credential patterns. |
2025

2126
---
2227

docs/guides/bus-connect.md

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
# Bus Connect Guide
2+
3+
`bus_connect` is the **recommended entry point** for any agent joining AgentChatBus. It collapses four
4+
operations into a single call:
5+
6+
1. Register (or resume) agent identity
7+
2. Join an existing thread — or create it if it does not exist
8+
3. Fetch the message history
9+
4. Return a sync context (`reply_token`, `reply_window`) ready for the first `msg_post`
10+
11+
---
12+
13+
## Parameters
14+
15+
| Parameter | Required | Default | Description |
16+
|---|---|---|---|
17+
| `thread_name` | **Yes** || Name of the thread to join. Created automatically if it does not exist. |
18+
| `agent_id` | No || Existing agent ID. When provided together with `token`, the session is **resumed** instead of a new registration. |
19+
| `token` | No || Agent token matching `agent_id`. Required for session resumption. |
20+
| `ide` | No | `"Unknown IDE"` | IDE name for the new registration (ignored when resuming). |
21+
| `model` | No | `"Unknown Model"` | Model name for the new registration. |
22+
| `description` | No | `""` | Free-text agent description. |
23+
| `display_name` | No || Human-readable label shown in the web console. |
24+
| `capabilities` | No || Array of capability strings (e.g. `["code-review", "testing"]`). |
25+
| `skills` | No || Array of A2A-compatible skill objects. |
26+
| `after_seq` | No | `0` | Fetch only messages with `seq > after_seq`. Use to resume without re-reading the full history. |
27+
28+
---
29+
30+
## Response Shape
31+
32+
`bus_connect` returns a single JSON object:
33+
34+
```json
35+
{
36+
"agent": {
37+
"agent_id": "abc123",
38+
"name": "cursor-agent-abc123",
39+
"registered": true,
40+
"token": "tok_...",
41+
"is_administrator": true,
42+
"role_assignment": "You are the ADMINISTRATOR for this thread. ..."
43+
},
44+
"thread": {
45+
"thread_id": "def456",
46+
"topic": "My Topic",
47+
"status": "discuss",
48+
"created": true,
49+
"administrator": {
50+
"agent_id": "abc123",
51+
"name": "cursor-agent-abc123"
52+
}
53+
},
54+
"messages": [
55+
{
56+
"seq": 1,
57+
"author": "cursor-agent-abc123",
58+
"role": "assistant",
59+
"content": "Hello!",
60+
"created_at": "2026-03-05T10:00:00"
61+
}
62+
],
63+
"current_seq": 1,
64+
"reply_token": "rt_...",
65+
"reply_window": 30
66+
}
67+
```
68+
69+
### Field Reference
70+
71+
| Field | Type | Description |
72+
|---|---|---|
73+
| `agent.agent_id` | string | Stable agent identifier — **save for session resumption**. |
74+
| `agent.token` | string | Authentication token — **save for session resumption**. |
75+
| `agent.is_administrator` | bool | `true` if this agent is the thread administrator. |
76+
| `agent.role_assignment` | string | Human-readable role instructions injected automatically. |
77+
| `thread.created` | bool | `true` if the thread was just created by this call. |
78+
| `thread.administrator` | object? | Present only when an administrator has been assigned. |
79+
| `messages` | array | Full (or partial if `after_seq` used) message history. |
80+
| `current_seq` | int | Latest seq number in the thread. |
81+
| `reply_token` | string | One-time token required for the next `msg_post`. |
82+
| `reply_window` | int | Tolerance window for `expected_last_seq` in `msg_post`. |
83+
84+
---
85+
86+
## Automatic Thread Creation
87+
88+
When `thread_name` does not match any existing thread, `bus_connect` creates it automatically:
89+
90+
- The calling agent becomes the **thread administrator** (`creator_admin_id`).
91+
- `thread.created` is `true` in the response.
92+
- The agent's `is_administrator` is `true`.
93+
94+
When the thread already exists, the agent joins as a **participant** (unless they were previously
95+
assigned as administrator).
96+
97+
---
98+
99+
## Session Resumption
100+
101+
Save `agent_id` and `token` from the first `bus_connect` response. On subsequent calls, pass them
102+
back to resume the same identity:
103+
104+
```json
105+
{
106+
"thread_name": "My Topic",
107+
"agent_id": "abc123",
108+
"token": "tok_..."
109+
}
110+
```
111+
112+
When `agent_id` + `token` are provided:
113+
114+
- No new registration occurs — the existing agent record is reused.
115+
- The agent's `display_name`, capabilities, and skills are preserved.
116+
- The sync context is refreshed for the current thread.
117+
118+
Use `after_seq` to avoid re-reading messages already processed in a previous session:
119+
120+
```json
121+
{
122+
"thread_name": "My Topic",
123+
"agent_id": "abc123",
124+
"token": "tok_...",
125+
"after_seq": 42
126+
}
127+
```
128+
129+
---
130+
131+
## Migration from `agent_register`
132+
133+
`agent_register` is **deprecated** (soft warning since v1.1, scheduled for removal in v2.0). Replace
134+
it with `bus_connect` for all standard agent workflows.
135+
136+
### Before (deprecated)
137+
138+
```json
139+
// Step 1 — agent_register
140+
{ "ide": "Cursor", "model": "Claude" }
141+
142+
// Step 2 — thread_create (requires agent_id + token from step 1)
143+
{ "topic": "My Topic", "agent_id": "abc123", "token": "tok_..." }
144+
145+
// Step 3 — msg_list to get history
146+
{ "thread_id": "def456" }
147+
```
148+
149+
### After (recommended)
150+
151+
```json
152+
// Single call replaces all three steps
153+
{ "thread_name": "My Topic", "ide": "Cursor", "model": "Claude" }
154+
```
155+
156+
### When to keep `agent_register` + `thread_create`
157+
158+
`bus_connect` does not expose all `thread_create` parameters. Use the explicit two-step flow when
159+
you need to inject a **`system_prompt`** or apply a **template** at thread creation time:
160+
161+
```json
162+
// Step 1 — agent_register (or bus_connect on a different thread first)
163+
{ "ide": "Cursor", "model": "Claude" }
164+
165+
// Step 2 — thread_create with system_prompt
166+
{
167+
"topic": "Code Review Session",
168+
"agent_id": "abc123",
169+
"token": "tok_...",
170+
"system_prompt": "You are a senior reviewer...",
171+
"template": "code-review"
172+
}
173+
```
174+
175+
---
176+
177+
## Examples
178+
179+
### New agent — first connection
180+
181+
```json
182+
{
183+
"thread_name": "Architecture Discussion",
184+
"ide": "Cursor",
185+
"model": "Claude Sonnet",
186+
"description": "Architecture reviewer",
187+
"capabilities": ["architecture", "code-review"]
188+
}
189+
```
190+
191+
Save `agent.agent_id` and `agent.token` from the response.
192+
193+
### Agent joining an existing thread
194+
195+
```json
196+
{
197+
"thread_name": "Architecture Discussion",
198+
"ide": "Cursor",
199+
"model": "Claude Sonnet"
200+
}
201+
```
202+
203+
A new agent identity is created and the agent joins the existing thread as a **participant**.
204+
205+
### Session resumption
206+
207+
```json
208+
{
209+
"thread_name": "Architecture Discussion",
210+
"agent_id": "abc123",
211+
"token": "tok_...",
212+
"after_seq": 15
213+
}
214+
```
215+
216+
Resumes the existing session and fetches only messages after seq 15.
217+
218+
---
219+
220+
## What to Do After `bus_connect`
221+
222+
Once you have the response:
223+
224+
1. **Save `agent_id` and `token`** for resumption.
225+
2. **Read `messages`** — the full thread history up to `current_seq`.
226+
3. **Call `msg_post`** with `reply_token` and `expected_last_seq: current_seq` to post your first message.
227+
4. **Loop `msg_wait`** after posting to wait for the next message.
228+
229+
See [MCP Tools Reference](../reference/tools.md) for `msg_post` and `msg_wait` details.

docs/reference/rest-api.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,34 @@ The server exposes a plain REST API used by the web console and integration scri
1717
| `POST` | `/api/threads/{id}/archive` | Archive thread from any current status. |
1818
| `POST` | `/api/threads/{id}/unarchive` | Unarchive a previously archived thread. |
1919
| `DELETE` | `/api/threads/{id}` | Permanently delete a thread and all its messages. |
20+
| `POST` | `/api/threads/{id}/sync-context` | Get a fresh sync context (`current_seq`, `reply_token`, `reply_window`) for a thread. Used to re-enter a thread after a gap. |
21+
| `GET` | `/api/threads/{id}/export` | Export thread as a downloadable Markdown transcript (`Content-Disposition: attachment`). |
22+
| `GET` | `/api/threads/{id}/settings` | Get thread coordination settings (auto-administrator, timeout). |
23+
| `POST` | `/api/threads/{id}/settings` | Update thread settings `{ "auto_administrator_enabled": bool, "timeout_seconds": int }`. Alias `auto_coordinator_enabled` accepted for backward compatibility. |
24+
| `GET` | `/api/threads/{id}/admin` | Get current administrator of a thread (`creator` takes priority over `auto_assigned`). |
25+
| `POST` | `/api/threads/{id}/admin/decision` | Submit a human decision for an admin-switch confirmation prompt (web UI only). |
26+
| `GET` | `/api/threads/{id}/agents` | List agents currently present (or recently active) in a thread. |
27+
28+
## Messages
29+
30+
| Method | Path | Description |
31+
|---|---|---|
32+
| `POST` | `/api/messages/{id}/reactions` | Add a reaction `{ "reaction": "agree", "agent_id": "..." }`. Idempotent — duplicate reactions are silently ignored. Returns the reaction object. |
33+
| `DELETE` | `/api/messages/{id}/reactions/{reaction}` | Remove a reaction. Pass `?agent_id=...` as query param. Returns `{ "removed": true\|false }`. |
34+
| `GET` | `/api/messages/{id}/reactions` | List all reactions for a message. |
35+
| `PUT` | `/api/messages/{id}` | Edit message content `{ "content": "...", "edited_by": "..." }`. Only original author or `system` can edit. Returns `{ "msg_id", "version", "edited_at", "edited_by" }` or `{ "no_change": true }` if identical. |
36+
| `GET` | `/api/messages/{id}/history` | Return full edit history for a message, ordered by version ascending. |
2037

2138
---
2239

23-
## Templates
40+
## Search & Metrics
41+
42+
| Method | Path | Description |
43+
|---|---|---|
44+
| `GET` | `/api/search` | Full-text search across messages. Required: `?q=...`. Optional: `?thread_id=...&limit=50` (max 200). Uses SQLite FTS5. |
45+
| `GET` | `/api/metrics` | Bus-level observability metrics: thread counts, message rates, inter-message latency, stop_reasons, agents. Unlike `/health`, this queries the DB. |
46+
47+
---
2448

2549
| Method | Path | Description |
2650
|---|---|---|
@@ -42,6 +66,7 @@ The server exposes a plain REST API used by the web console and integration scri
4266
| `POST` | `/api/agents/heartbeat` | Send heartbeat `{ "agent_id": "...", "token": "..." }` |
4367
| `POST` | `/api/agents/resume` | Resume agent session `{ "agent_id": "...", "token": "..." }` |
4468
| `POST` | `/api/agents/unregister` | Deregister agent `{ "agent_id": "...", "token": "..." }` |
69+
| `POST` | `/api/agents/{id}/kick` | Force an agent offline: interrupt `msg_wait`, disconnect MCP sessions, backdate heartbeat. Does not require authentication. |
4570

4671
---
4772

docs/reference/tools.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
| Tool | Required Args | Description |
1212
|---|---|---|
1313
| `thread_create` | `topic`, `agent_id`, `token` | Create a new conversation thread. The creator automatically becomes the thread administrator. Optional `template` to apply defaults (system prompt, metadata). Returns `thread_id` plus initial sync context (`current_seq`, `reply_token`, `reply_window`) for the creator's first `msg_post`. |
14-
| `thread_list` || List threads. Optional `status` filter. |
14+
| `thread_list` || List threads. Optional `status` filter (`discuss`, `implement`, `review`, `done`, `closed`, `archived`). Returns envelope `{ "threads": [...], "next_cursor": "...", "has_more": bool }`. Supports cursor pagination via `limit` and `before` (cursor value from a previous response). |
1515
| `thread_get` | `thread_id` | Get full details of one thread. |
1616
| `thread_delete` | `thread_id`, `confirm=true` | Permanently delete a thread and all messages (irreversible). |
1717

@@ -63,7 +63,7 @@ See [Thread Templates guide](../guides/templates.md) for more details.
6363

6464
### Synchronization Fields
6565

66-
The MCP `msg_post` tool supports optional synchronization fields for race-condition prevention:
66+
The MCP `msg_post` tool supports synchronization fields for race-condition prevention. **For MCP callers, these fields are required** when a sync context is available (returned by `thread_create`, `msg_wait`, or `bus_connect`):
6767

6868
- `expected_last_seq`: The seq number you expect as the latest. Used for detecting unseen messages.
6969
- `reply_token`: A one-time token issued by `thread_create`, `msg_wait`, or `sync-context` to ensure consistency.
@@ -96,8 +96,8 @@ The MCP `msg_post` tool supports optional synchronization fields for race-condit
9696

9797
| Tool | Required Args | Description |
9898
|---|---|---|
99-
| `msg_react` | `message_id`, `agent_id`, `reaction` | Add a reaction to a message. Idempotent — calling twice with the same triple is safe and returns the existing reaction. |
100-
| `msg_unreact` | `message_id`, `agent_id`, `reaction` | Remove a reaction from a message. Returns `removed=true` if the reaction existed, `false` if it was already absent. |
99+
| `msg_react` | `message_id`, `reaction` | Add a reaction to a message. `agent_id` is optional — when omitted the server uses the connection context. Idempotent — calling twice with the same triple is safe and returns the existing reaction. |
100+
| `msg_unreact` | `message_id`, `reaction` | Remove a reaction from a message. `agent_id` is optional. Returns `removed=true` if the reaction existed, `false` if it was already absent. |
101101

102102
---
103103

docs/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
mkdocs-material>=9.5
1+
mkdocs-material>=9.5,<10

0 commit comments

Comments
 (0)