1186 lines
28 KiB
Markdown
1186 lines
28 KiB
Markdown
# cc-connect Management API Specification
|
||
|
||
> **Version:** 1.1-draft
|
||
> **Status:** Draft — subject to change before implementation
|
||
> **Last Updated:** 2026-03-24
|
||
|
||
---
|
||
|
||
## 1. Overview
|
||
|
||
The cc-connect Management API is an HTTP-based REST API that enables external applications (web dashboards, TUI clients, GUI desktop apps, Mac tray apps) to manage and monitor cc-connect instances. It complements the existing internal Unix socket API by providing a network-accessible, token-authenticated interface suitable for remote and local management tools.
|
||
|
||
### 1.1 Architecture
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────────┐
|
||
│ cc-connect Process │
|
||
│ │
|
||
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
|
||
│ │ Unix Socket API │ │ Management API │ │ Bridge Server │ │
|
||
│ │ (internal) │ │ (HTTP :9820) │ │ (WebSocket) │ │
|
||
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
|
||
│ │ │ │ │
|
||
│ └───────────────────────┼───────────────────────┘ │
|
||
│ │ │
|
||
│ ┌────────┴────────┐ │
|
||
│ │ Core Engine(s) │ │
|
||
│ │ Projects │ │
|
||
│ │ Sessions │ │
|
||
│ │ Cron/Heartbeat │ │
|
||
│ └─────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────────────┘
|
||
│
|
||
┌─────────────────────┼─────────────────────┐
|
||
│ │ │
|
||
┌────────┴────────┐ ┌───────┴───────┐ ┌─────────┴─────────┐
|
||
│ Web Dashboard │ │ TUI Client │ │ Mac Tray App │
|
||
└─────────────────┘ └───────────────┘ └────────────────────┘
|
||
```
|
||
|
||
### 1.2 Design Principles
|
||
|
||
- **RESTful:** Resource-oriented URLs, standard HTTP methods
|
||
- **JSON:** All request/response bodies use `application/json`
|
||
- **Consistent envelope:** Every response uses `{"ok": true|false, "data"|"error": ...}`
|
||
- **Token auth:** Bearer token or query parameter for all endpoints
|
||
|
||
---
|
||
|
||
## 2. Configuration
|
||
|
||
### 2.1 Management Block
|
||
|
||
Add the following to `config.toml`:
|
||
|
||
```toml
|
||
[management]
|
||
enabled = true
|
||
port = 9820
|
||
token = "mgmt-secret"
|
||
```
|
||
|
||
| Field | Type | Default | Description |
|
||
|----------|---------|-----------|--------------------------------------------------|
|
||
| `enabled`| boolean | `false` | Enable the Management API server |
|
||
| `port` | integer | `9820` | TCP port to listen on |
|
||
| `token` | string | (required)| Shared secret for authentication |
|
||
|
||
When `enabled` is `false`, the Management API is not started. The token should be a strong, random string (e.g. 32+ characters).
|
||
|
||
### 2.2 Base URL
|
||
|
||
All endpoints are relative to:
|
||
|
||
```
|
||
http://<host>:<port>/api/v1
|
||
```
|
||
|
||
Example: `http://localhost:9820/api/v1/status`
|
||
|
||
---
|
||
|
||
## 3. Authentication
|
||
|
||
Every request must include a valid token. Two methods are supported:
|
||
|
||
### 3.1 Bearer Token (Recommended)
|
||
|
||
```
|
||
Authorization: Bearer <token>
|
||
```
|
||
|
||
Example:
|
||
|
||
```bash
|
||
curl -H "Authorization: Bearer mgmt-secret" http://localhost:9820/api/v1/status
|
||
```
|
||
|
||
### 3.2 Query Parameter
|
||
|
||
```
|
||
GET /api/v1/status?token=mgmt-secret
|
||
```
|
||
|
||
> **Note:** Query parameter auth is provided for environments where setting headers is difficult. Prefer Bearer token for security (tokens in URLs may be logged).
|
||
|
||
### 3.3 Unauthorized Response
|
||
|
||
If the token is missing or invalid:
|
||
|
||
- **HTTP Status:** `401 Unauthorized`
|
||
- **Body:**
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "unauthorized: missing or invalid token"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Response Format
|
||
|
||
### 4.1 Success
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": { ... }
|
||
}
|
||
```
|
||
|
||
### 4.2 Error
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "human-readable error message"
|
||
}
|
||
```
|
||
|
||
### 4.3 HTTP Status Codes
|
||
|
||
| Code | Meaning |
|
||
|------|----------------------------------------------|
|
||
| 200 | Success |
|
||
| 400 | Bad request (invalid body, missing params) |
|
||
| 401 | Unauthorized (missing/invalid token) |
|
||
| 404 | Resource not found (project, session, etc.) |
|
||
| 405 | Method not allowed |
|
||
| 500 | Internal server error |
|
||
|
||
---
|
||
|
||
## 5. Endpoint Reference
|
||
|
||
### 5.1 System
|
||
|
||
#### GET /api/v1/status
|
||
|
||
Returns system status and summary.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"version": "v1.2.0",
|
||
"uptime_seconds": 3600,
|
||
"connected_platforms": ["feishu", "telegram"],
|
||
"projects_count": 2,
|
||
"bridge_adapters": [
|
||
{
|
||
"platform": "custom",
|
||
"project": "my-backend",
|
||
"capabilities": ["text", "images"]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|-----------------------|----------|--------------------------------------------------|
|
||
| `version` | string | cc-connect version (e.g. `v1.2.0`) |
|
||
| `uptime_seconds` | number | Process uptime in seconds |
|
||
| `connected_platforms` | string[] | Platform types currently connected |
|
||
| `projects_count` | number | Number of configured projects |
|
||
| `bridge_adapters` | array | External adapters connected via Bridge WebSocket |
|
||
|
||
---
|
||
|
||
#### POST /api/v1/restart
|
||
|
||
Triggers a graceful restart. The process will shut down cleanly and exec itself. A "restart successful" message may be sent to the session that initiated the restart (if applicable).
|
||
|
||
**Request body (optional):**
|
||
|
||
```json
|
||
{
|
||
"session_key": "telegram:123:456",
|
||
"platform": "telegram"
|
||
}
|
||
```
|
||
|
||
If provided, the restart notification will be sent to the specified session after the new process starts.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "restart initiated"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/reload
|
||
|
||
Reloads configuration from disk without restarting the process. New projects may be added; removed projects are stopped. Changed project settings take effect.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "config reloaded",
|
||
"projects_added": ["new-project"],
|
||
"projects_removed": [],
|
||
"projects_updated": ["my-backend"]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### GET /api/v1/config
|
||
|
||
Returns the current configuration with secrets redacted. Useful for debugging and UI display.
|
||
|
||
**Query parameters:** None
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"data_dir": "/home/user/.cc-connect",
|
||
"language": "en",
|
||
"projects": [
|
||
{
|
||
"name": "my-backend",
|
||
"agent": {
|
||
"type": "claudecode",
|
||
"providers": [
|
||
{
|
||
"name": "anthropic",
|
||
"api_key": "***",
|
||
"base_url": "",
|
||
"model": "claude-sonnet-4-20250514"
|
||
}
|
||
]
|
||
},
|
||
"platforms": [
|
||
{
|
||
"type": "feishu",
|
||
"options": {
|
||
"app_id": "***",
|
||
"app_secret": "***"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
Secrets (e.g. `api_key`, `token`, `app_secret`, `client_secret`) are replaced with `"***"`.
|
||
|
||
---
|
||
|
||
#### GET /api/v1/logs
|
||
|
||
Returns recent log entries.
|
||
|
||
**Query parameters:**
|
||
|
||
| Param | Type | Default | Description |
|
||
|---------|--------|---------|--------------------------------------|
|
||
| `level` | string | `info` | Minimum level: `debug`, `info`, `warn`, `error` |
|
||
| `limit` | int | `100` | Max entries to return (1–1000) |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"entries": [
|
||
{
|
||
"time": "2026-03-10T10:30:00Z",
|
||
"level": "info",
|
||
"message": "api server started",
|
||
"attrs": {"socket": "/home/user/.cc-connect/run/api.sock"}
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.2 Projects
|
||
|
||
#### GET /api/v1/projects
|
||
|
||
Lists all projects with a summary.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"projects": [
|
||
{
|
||
"name": "my-backend",
|
||
"agent_type": "claudecode",
|
||
"platforms": ["feishu", "telegram"],
|
||
"sessions_count": 3,
|
||
"heartbeat_enabled": true
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### GET /api/v1/projects/{name}
|
||
|
||
Returns detailed information for a single project.
|
||
|
||
**Path parameters:**
|
||
|
||
| Param | Type | Description |
|
||
|--------|--------|--------------------|
|
||
| `name` | string | Project name |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"name": "my-backend",
|
||
"agent_type": "claudecode",
|
||
"platforms": [
|
||
{
|
||
"type": "feishu",
|
||
"connected": true
|
||
},
|
||
{
|
||
"type": "telegram",
|
||
"connected": true
|
||
}
|
||
],
|
||
"sessions_count": 3,
|
||
"active_session_keys": ["telegram:123:456", "feishu:ou_xxx:chat_xxx"],
|
||
"heartbeat": {
|
||
"enabled": true,
|
||
"paused": false,
|
||
"interval_mins": 30,
|
||
"session_key": "telegram:123:456"
|
||
},
|
||
"settings": {
|
||
"quiet": false,
|
||
"admin_from": "user1,user2",
|
||
"language": "en",
|
||
"disabled_commands": ["restart", "upgrade"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**Error (404):**
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "project not found: my-backend"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### PATCH /api/v1/projects/{name}
|
||
|
||
Updates project settings. Only provided fields are updated.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"quiet": true,
|
||
"admin_from": "user1,user2,user3",
|
||
"language": "zh",
|
||
"disabled_commands": ["restart", "upgrade", "cron"]
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|---------------------|----------|----------------------------------------------------------|
|
||
| `quiet` | boolean | Suppress thinking/tool progress messages |
|
||
| `admin_from` | string | Comma-separated user IDs for privileged commands; `"*"` = all |
|
||
| `language` | string | UI language: `en`, `zh`, `zh-TW`, `ja`, `es` |
|
||
| `disabled_commands` | string[] | Commands to disable (e.g. `restart`, `upgrade`, `cron`) |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"name": "my-backend",
|
||
"settings": {
|
||
"quiet": true,
|
||
"admin_from": "user1,user2,user3",
|
||
"language": "zh",
|
||
"disabled_commands": ["restart", "upgrade", "cron"]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.3 Sessions
|
||
|
||
Sessions are conversation contexts within a project. A session is identified by a `session_key` (format: `platform:chatId:userId`) and optionally by an internal `id` for named sessions (e.g. `/new work` creates a named session).
|
||
|
||
#### GET /api/v1/projects/{name}/sessions
|
||
|
||
Lists sessions for a project with summary info including the last message preview.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"sessions": [
|
||
{
|
||
"id": "sess_abc123",
|
||
"session_key": "telegram:123:456",
|
||
"name": "work",
|
||
"platform": "telegram",
|
||
"agent_type": "claudecode",
|
||
"active": true,
|
||
"live": true,
|
||
"history_count": 12,
|
||
"created_at": "2026-03-10T09:00:00Z",
|
||
"updated_at": "2026-03-10T10:30:00Z",
|
||
"last_message": {
|
||
"role": "assistant",
|
||
"content": "Done! The tests are passing now...",
|
||
"timestamp": "2026-03-10T10:30:00Z"
|
||
},
|
||
"user_name": "Alice",
|
||
"chat_name": "dev-channel"
|
||
}
|
||
],
|
||
"active_keys": {
|
||
"telegram:123:456": "telegram"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|----------------|---------|-------------------------------------------------------------------|
|
||
| `active` | boolean | Whether this is the selected session for its user key |
|
||
| `live` | boolean | Whether there is a running agent process for this session |
|
||
| `last_message` | object | Preview of the last message (role, content truncated to 200 chars, timestamp). `null` if no history. |
|
||
| `user_name` | string | Display name of the user (from platform metadata) |
|
||
| `chat_name` | string | Name of the chat/channel (from platform metadata) |
|
||
| `active_keys` | object | Map of session keys with active agent connections → platform name |
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/sessions
|
||
|
||
Creates a new session.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"session_key": "telegram:123:456",
|
||
"name": "work"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|--------------|--------|----------|--------------------------------------|
|
||
| `session_key`| string | yes | Platform routing key (e.g. `telegram:123:456`) |
|
||
| `name` | string | no | Human-readable session name |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"id": "sess_xyz789",
|
||
"session_key": "telegram:123:456",
|
||
"name": "work",
|
||
"created_at": "2026-03-10T10:35:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### GET /api/v1/projects/{name}/sessions/{id}
|
||
|
||
Returns session detail including message history.
|
||
|
||
**Path parameters:**
|
||
|
||
| Param | Type | Description |
|
||
|--------|--------|--------------------------------------|
|
||
| `name` | string | Project name |
|
||
| `id` | string | Session ID |
|
||
|
||
**Query parameters:**
|
||
|
||
| Param | Type | Default | Description |
|
||
|---------|------|---------|--------------------------------|
|
||
| `history_limit` | int | 50 | Max history entries to return |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"id": "sess_abc123",
|
||
"session_key": "telegram:123:456",
|
||
"name": "work",
|
||
"platform": "telegram",
|
||
"agent_type": "claudecode",
|
||
"agent_session_id": "as_xxx",
|
||
"active": true,
|
||
"live": true,
|
||
"history_count": 12,
|
||
"created_at": "2026-03-10T09:00:00Z",
|
||
"updated_at": "2026-03-10T10:30:00Z",
|
||
"history": [
|
||
{
|
||
"role": "user",
|
||
"content": "Hello",
|
||
"timestamp": "2026-03-10T09:00:05Z"
|
||
},
|
||
{
|
||
"role": "assistant",
|
||
"content": "Hi! How can I help?",
|
||
"timestamp": "2026-03-10T09:00:10Z"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
| Field | Type | Description |
|
||
|---------|---------|---------------------------------------------------------------|
|
||
| `live` | boolean | Whether the session has an active agent process (can receive messages via `/send`) |
|
||
|
||
---
|
||
|
||
#### DELETE /api/v1/projects/{name}/sessions/{id}
|
||
|
||
Deletes a session and its history.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "session deleted"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/sessions/switch
|
||
|
||
Switches the active session for a given session_key (e.g. when a user has multiple named sessions).
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"session_key": "telegram:123:456",
|
||
"session_id": "sess_xyz789"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---------------|--------|----------|--------------------------------|
|
||
| `session_key` | string | yes | Platform routing key |
|
||
| `session_id` | string | yes | Session ID to make active |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "active session switched",
|
||
"active_session_id": "sess_xyz789"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/send
|
||
|
||
Sends a message to a session. The message is delivered to the agent as if the user had sent it via the platform. **Requires the session to be live** (i.e., have an active agent process). Check the `live` field from session detail to verify before sending.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"session_key": "telegram:123:456",
|
||
"message": "Review the latest commit"
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|---------------|--------|----------|--------------------------------|
|
||
| `session_key`| string | yes | Platform routing key |
|
||
| `message` | string | yes | Text to send to the agent |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "message sent"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.4 Providers
|
||
|
||
Providers are API backends (e.g. Anthropic, OpenAI, custom endpoints) that supply the AI model for a project's agent.
|
||
|
||
#### GET /api/v1/projects/{name}/providers
|
||
|
||
Lists providers with active indicator.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"providers": [
|
||
{
|
||
"name": "anthropic",
|
||
"active": true,
|
||
"model": "claude-sonnet-4-20250514",
|
||
"base_url": ""
|
||
},
|
||
{
|
||
"name": "relay",
|
||
"active": false,
|
||
"model": "claude-sonnet-4-20250514",
|
||
"base_url": "https://api.relay.example.com"
|
||
}
|
||
],
|
||
"active_provider": "anthropic"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/providers
|
||
|
||
Adds a new provider.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"name": "relay",
|
||
"api_key": "sk-xxx",
|
||
"base_url": "https://api.relay.example.com",
|
||
"model": "claude-sonnet-4-20250514",
|
||
"thinking": "disabled",
|
||
"env": {
|
||
"CLAUDE_CODE_USE_BEDROCK": "1",
|
||
"AWS_PROFILE": "bedrock"
|
||
}
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|-----------|-----------------|----------|------------------------------------------|
|
||
| `name` | string | yes | Provider identifier |
|
||
| `api_key` | string | no* | API key (*required if no `env`) |
|
||
| `base_url`| string | no | Custom API endpoint |
|
||
| `model` | string | no | Model override |
|
||
| `thinking`| string | no | `"disabled"` for providers without adaptive thinking |
|
||
| `env` | object (k/v) | no | Extra environment variables |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"name": "relay",
|
||
"message": "provider added"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### DELETE /api/v1/projects/{name}/providers/{provider}
|
||
|
||
Removes a provider. The active provider cannot be removed; switch first.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "provider removed"
|
||
}
|
||
}
|
||
```
|
||
|
||
**Error (400):**
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "cannot remove active provider; switch to another first"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/providers/{provider}/activate
|
||
|
||
Switches the active provider.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"active_provider": "relay",
|
||
"message": "provider activated"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### GET /api/v1/projects/{name}/models
|
||
|
||
Lists available models for the project's agent type.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"models": [
|
||
"claude-sonnet-4-20250514",
|
||
"claude-3-5-sonnet-20241022",
|
||
"claude-3-opus-20240229"
|
||
],
|
||
"current": "claude-sonnet-4-20250514"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/model
|
||
|
||
Sets the model for the project.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"model": "claude-3-5-sonnet-20241022"
|
||
}
|
||
```
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"model": "claude-3-5-sonnet-20241022",
|
||
"message": "model updated"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.5 Cron Jobs
|
||
|
||
#### GET /api/v1/cron
|
||
|
||
Lists all cron jobs, optionally filtered by project.
|
||
|
||
**Query parameters:**
|
||
|
||
| Param | Type | Description |
|
||
|-----------|--------|--------------------|
|
||
| `project` | string | Filter by project |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"jobs": [
|
||
{
|
||
"id": "cron_abc123",
|
||
"project": "my-backend",
|
||
"session_key": "telegram:123:456",
|
||
"cron_expr": "0 6 * * *",
|
||
"prompt": "Summarize GitHub trending",
|
||
"exec": "",
|
||
"work_dir": "",
|
||
"description": "Daily GitHub Trending",
|
||
"enabled": true,
|
||
"silent": true,
|
||
"created_at": "2026-03-10T08:00:00Z",
|
||
"last_run": "2026-03-10T06:00:00Z",
|
||
"last_error": ""
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/cron
|
||
|
||
Adds a cron job. Either `prompt` or `exec` must be provided, not both.
|
||
|
||
**Request body (prompt job):**
|
||
|
||
```json
|
||
{
|
||
"project": "my-backend",
|
||
"session_key": "telegram:123:456",
|
||
"cron_expr": "0 6 * * *",
|
||
"prompt": "Summarize GitHub trending",
|
||
"description": "Daily GitHub Trending",
|
||
"silent": true
|
||
}
|
||
```
|
||
|
||
**Request body (exec job):**
|
||
|
||
```json
|
||
{
|
||
"project": "my-backend",
|
||
"session_key": "telegram:123:456",
|
||
"cron_expr": "0 9 * * 1",
|
||
"exec": "npm run weekly-report",
|
||
"work_dir": "/path/to/project",
|
||
"description": "Weekly Report",
|
||
"silent": false
|
||
}
|
||
```
|
||
|
||
| Field | Type | Required | Description |
|
||
|--------------|---------|----------|------------------------------------------------|
|
||
| `project` | string | no* | Project name (*required if multiple projects) |
|
||
| `session_key`| string | yes | Target session for prompt jobs |
|
||
| `cron_expr` | string | yes | Cron expression (5 or 6 fields) |
|
||
| `prompt` | string | no* | Prompt to send (*required if no `exec`) |
|
||
| `exec` | string | no* | Shell command (*required if no `prompt`) |
|
||
| `work_dir` | string | no | Working directory for exec |
|
||
| `description`| string | no | Human-readable label |
|
||
| `silent` | boolean | no | Suppress start notification |
|
||
| `session_mode` | string | no | `reuse` (default) or `new_per_run` — new agent session each run |
|
||
| `timeout_mins` | int | no | Scheduler wait per run: omit = 30 min, `0` = no time limit |
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"id": "cron_xyz789",
|
||
"project": "my-backend",
|
||
"session_key": "telegram:123:456",
|
||
"cron_expr": "0 6 * * *",
|
||
"prompt": "Summarize GitHub trending",
|
||
"description": "Daily GitHub Trending",
|
||
"enabled": true,
|
||
"created_at": "2026-03-10T10:40:00Z"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### DELETE /api/v1/cron/{id}
|
||
|
||
Deletes a cron job.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "cron job deleted"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.6 Heartbeat
|
||
|
||
Heartbeat runs periodic prompts in a session (e.g. "check inbox") to keep the agent aware of the environment.
|
||
|
||
#### GET /api/v1/projects/{name}/heartbeat
|
||
|
||
Returns heartbeat status.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"enabled": true,
|
||
"paused": false,
|
||
"interval_mins": 30,
|
||
"only_when_idle": true,
|
||
"session_key": "telegram:123:456",
|
||
"silent": true,
|
||
"run_count": 42,
|
||
"error_count": 0,
|
||
"skipped_busy": 5,
|
||
"last_run": "2026-03-10T10:00:00Z",
|
||
"last_error": ""
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/heartbeat/pause
|
||
|
||
Pauses heartbeat.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "heartbeat paused"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/heartbeat/resume
|
||
|
||
Resumes heartbeat.
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "heartbeat resumed"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/heartbeat/run
|
||
|
||
Triggers heartbeat immediately (one-shot).
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"message": "heartbeat triggered"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### POST /api/v1/projects/{name}/heartbeat/interval
|
||
|
||
Sets the heartbeat interval.
|
||
|
||
**Request body:**
|
||
|
||
```json
|
||
{
|
||
"minutes": 15
|
||
}
|
||
```
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"interval_mins": 15,
|
||
"message": "interval updated"
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### 5.7 Bridge
|
||
|
||
#### GET /api/v1/bridge/adapters
|
||
|
||
Lists connected bridge adapters (external platforms via WebSocket).
|
||
|
||
**Response:**
|
||
|
||
```json
|
||
{
|
||
"ok": true,
|
||
"data": {
|
||
"adapters": [
|
||
{
|
||
"platform": "custom",
|
||
"project": "my-backend",
|
||
"capabilities": ["text", "images", "files"],
|
||
"connected_at": "2026-03-10T09:00:00Z"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Error Handling Conventions
|
||
|
||
### 6.1 Standard Error Response
|
||
|
||
All errors use the same envelope:
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "human-readable message"
|
||
}
|
||
```
|
||
|
||
### 6.2 Common Errors
|
||
|
||
| HTTP | Error message example | Cause |
|
||
|------|-------------------------------------------------|--------------------------------|
|
||
| 400 | `"project is required (multiple projects)"` | Missing required parameter |
|
||
| 400 | `"either prompt or exec is required"` | Invalid cron job body |
|
||
| 401 | `"unauthorized: missing or invalid token"` | Auth failure |
|
||
| 404 | `"project not found: xyz"` | Unknown project/session/cron |
|
||
| 404 | `"session not found"` | Unknown session ID |
|
||
| 405 | `"method not allowed"` | Wrong HTTP method |
|
||
| 500 | `"internal error"` | Unexpected server error |
|
||
|
||
### 6.3 Validation Errors
|
||
|
||
When request body validation fails:
|
||
|
||
```json
|
||
{
|
||
"ok": false,
|
||
"error": "invalid request: session_key is required"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Session Key Format
|
||
|
||
The `session_key` is a composite identifier used to route messages to the correct platform and chat:
|
||
|
||
```
|
||
<platform>:<chat_id>:<user_id>
|
||
```
|
||
|
||
Examples:
|
||
|
||
- `telegram:123456789:123456789` — Telegram user 123456789 in chat 123456789
|
||
- `feishu:ou_xxx:chat_yyy` — Feishu user in chat
|
||
- `slack:C01234:U05678` — Slack channel and user
|
||
- `discord:123456789:987654321` — Discord guild and user
|
||
|
||
For multi-workspace mode, the format may include a workspace prefix:
|
||
|
||
```
|
||
<workspace>:<platform>:<chat_id>:<user_id>
|
||
```
|
||
|
||
---
|
||
|
||
## 8. CORS
|
||
|
||
When the Management API is used by web dashboards, CORS headers should be configurable. A suggested config extension:
|
||
|
||
```toml
|
||
[management]
|
||
enabled = true
|
||
port = 9820
|
||
token = "mgmt-secret"
|
||
cors_origins = ["http://localhost:3000", "https://dashboard.example.com"]
|
||
```
|
||
|
||
If not configured, CORS may be disabled or use a default (e.g. `*` for same-origin only).
|
||
|
||
---
|
||
|
||
## 9. Changelog
|
||
|
||
| Version | Date | Changes |
|
||
|-----------|------------|----------------------------|
|
||
| 1.1-draft | 2026-03-24 | Enrich session list/detail with `live`, `last_message`, `agent_type`, `user_name`, `chat_name`, `active_keys` fields |
|
||
| 1.0-draft | 2026-03-10 | Initial specification |
|
||
|
||
---
|
||
|
||
## 10. References
|
||
|
||
- [Bridge Protocol](bridge-protocol.md) — WebSocket protocol for external platform adapters
|
||
- [Usage Guide](usage.md) — End-user features and slash commands
|
||
- [config.example.toml](../config.example.toml) — Configuration template
|