All checks were successful
Build and Push Docker Image / build (push) Successful in 1m15s
Reviewed-on: MoA/agent#1 Co-authored-by: highperfocused <highperfocused@pm.me> Co-committed-by: highperfocused <highperfocused@pm.me>
140 lines
2.9 KiB
Markdown
140 lines
2.9 KiB
Markdown
# MoA Agent Gateway
|
|
|
|
This project now runs as a **chat gateway** in front of `@mariozechner/pi-coding-agent`.
|
|
|
|
It supports:
|
|
- long-lived agent conversations
|
|
- HTTP JSON API
|
|
- streaming responses via Server-Sent Events (SSE)
|
|
- a built-in browser chat UI at `/`
|
|
|
|
You can also keep one-shot mode (`RUN_MODE=single`) for script usage.
|
|
|
|
---
|
|
|
|
## Documentation
|
|
|
|
- Gateway internals: `docs/gateway.md`
|
|
- Web UI internals: `docs/web-ui.md`
|
|
- Channel integrations (Web UI, Slack, Matrix, custom): `docs/channels.md`
|
|
|
|
---
|
|
|
|
## Run
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
# set provider/model/key in .env
|
|
|
|
docker compose up --build
|
|
```
|
|
|
|
Gateway default URL:
|
|
- `http://localhost:8787`
|
|
|
|
Health check:
|
|
|
|
```bash
|
|
curl http://localhost:8787/health
|
|
```
|
|
|
|
One-shot mode (legacy behavior):
|
|
|
|
```bash
|
|
RUN_MODE=single PROMPT="List files" npm start
|
|
```
|
|
|
|
---
|
|
|
|
## API
|
|
|
|
### Create/list conversations
|
|
|
|
```bash
|
|
curl -X POST http://localhost:8787/v1/conversations \
|
|
-H 'content-type: application/json' \
|
|
-d '{"conversationId":"web:user-42:chat-a"}'
|
|
|
|
curl http://localhost:8787/v1/conversations
|
|
```
|
|
|
|
### Chat (non-streaming)
|
|
|
|
```bash
|
|
curl -X POST http://localhost:8787/v1/chat \
|
|
-H 'content-type: application/json' \
|
|
-d '{"conversationId":"web:user-42:chat-a","message":"Summarize this repo"}'
|
|
```
|
|
|
|
### Chat (streaming SSE)
|
|
|
|
```bash
|
|
curl -N -X POST http://localhost:8787/v1/chat/stream \
|
|
-H 'content-type: application/json' \
|
|
-d '{"conversationId":"web:user-42:chat-a","message":"List TypeScript files"}'
|
|
```
|
|
|
|
### Adapter-friendly endpoint (Slack/Matrix/etc)
|
|
|
|
Instead of constructing `conversationId` in your adapter, you can call:
|
|
|
|
- `POST /v1/adapters/chat`
|
|
- `POST /v1/adapters/chat/stream`
|
|
|
|
Body fields:
|
|
|
|
```json
|
|
{
|
|
"source": "slack",
|
|
"workspaceId": "T123",
|
|
"channelId": "C456",
|
|
"threadId": "1712233.991",
|
|
"userId": "U789",
|
|
"message": "Summarize the thread"
|
|
}
|
|
```
|
|
|
|
The gateway derives a stable conversation id:
|
|
`source:workspaceId:channelId:threadId`
|
|
|
|
SSE events include:
|
|
- `assistant_text_delta`
|
|
- `assistant_thinking_delta`
|
|
- `tool_start`, `tool_update`, `tool_end`
|
|
- `agent_start`, `agent_end`
|
|
- `done` (final response payload)
|
|
- `error`
|
|
|
|
---
|
|
|
|
## Built-in Web UI
|
|
|
|
Open:
|
|
|
|
- `http://localhost:8787/`
|
|
|
|
The UI stores `conversationId` in local storage and reuses it to keep context.
|
|
|
|
---
|
|
|
|
## Auth and CORS
|
|
|
|
Optional env vars:
|
|
- `GATEWAY_AUTH_TOKEN`: require `Authorization: Bearer <token>`
|
|
- `GATEWAY_CORS_ORIGIN`: e.g. `*` or `https://my-ui.example`
|
|
|
|
---
|
|
|
|
## Multi-client strategy (Slack / Matrix / custom UI)
|
|
|
|
The gateway is transport-agnostic. For each upstream client, map its thread identity to a stable `conversationId`, for example:
|
|
|
|
- Web: `web:<userId>:<chatId>`
|
|
- Slack: `slack:<teamId>:<channelId>:<threadTs>`
|
|
- Matrix: `matrix:<roomId>:<threadRootEventId>`
|
|
|
|
Then post messages to `/v1/chat` or `/v1/chat/stream` with that `conversationId`.
|
|
|
|
This keeps one agent session per thread across transports.
|
|
For detailed setup guidance per transport, see `docs/channels.md`.
|