Files
ars-backend/README.md
ROOG 59d4831f00 main: 增强工具调用与消息流程
- 支持 tool.call 和 tool.result 消息类型处理
- 引入 Tool 调度与执行逻辑,支持超时与结果截断
- 增加 ToolRegistry 和 ToolExecutor 管理工具定义与执行
- 更新上下文构建与消息映射逻辑,适配工具闭环处理
- 扩展配置与环境变量,支持 Tool 调用相关选项
- 增强单元测试覆盖工具调用与执行情景
- 更新文档和 OpenAPI,新增工具相关说明与模型定义
2025-12-22 12:36:59 +08:00

100 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Agent Runtime Server (ARS) · Laravel + Octane + Docker
> 自建可部署的 Agent Runtime Server。愿景兼容大部分 Agent 模型、随时在 Web 终端输入指令/查看日志、断开后任务继续执行,重新连入能续上会话。
>
> “输入 prompt 就能离开工位,路上/手机继续 approve 和观察”。
## 🎯 愿景与思路(摘录)
- 兼容多数 Agent 模型,提供可观测的运行日志。
- Web 终端可随时输入/查看;断线不中断,重连可续。
- 面向开源生态,避免被单一厂商闭锁;先做最小实现,再逐步拆分组件。
## 🏗️ 当前架构概览
- **运行**Docker ComposeFrankenPHP + Laravel Octane。
- **存储**PostgreSQL主存储Redis可选用于 SSE 推送messages.payload 提供表达式索引以加速 run/cancel 查询。
- **鉴权**JWT无状态API 路由均在 `/api/*`
- **会话/消息模型**
- `chat_sessions(session_id UUID, session_name, status OPEN|LOCKED|CLOSED, last_seq, last_message_id, timestamps)`
- `messages(message_id UUID, session_id, role USER|AGENT|TOOL|SYSTEM, type, content, payload jsonb, seq, reply_to, dedupe_key)`
- 约束:`unique(session_id, seq)``unique(session_id, dedupe_key)`append 行锁 + 事务seq 单调递增。
- **实时**SSE `/api/sessions/{id}/sse`backlog 先补历史(按 seq再监听 Redis `session:{id}:messages` 渠道;发现 seq gap 会回补并提供心跳。
- **Agent Run 编排MVP-0**user.prompt 后自动触发 RunDispatcher → `run.status=RUNNING` → AgentRunJobHttpProvider未配置 endpoint 时回退 DummyProvider`agent.message` + `run.status=DONE/FAILED/CANCELED` 落库;同 trigger_message 幂等、同会话只允许一个 RUNNING终态/消息均去重,取消可保证不写 agent.message。
- **队列监控**Horizon本地默认开放 `/horizon`,非 local 环境默认拒绝访问)。
## 🚀 快速启动
```bash
# 构建并启动
docker compose build
docker compose up -d app horizon pgsql redis
# 首次迁移(仅需一次)
docker compose exec app php artisan migrate
# 运行 Feature 测试
docker compose exec app php artisan test --testsuite=Feature
# 队列AgentRunJob开发可用同步队列或用 Horizon
# 同步:.env / phpunit.xml 中 QUEUE_CONNECTION=sync
# Horizondocker compose up -d horizon需 composer install 安装 laravel/horizonQUEUE_CONNECTION=redis
```
### Agent Provider 配置(可选)
`config/agent.php` 读取以下环境变量(默认值已内置),用于控制 HTTP 调用、OpenAI 直连以及队列重试:
- `AGENT_PROVIDER_ENDPOINT`:自定义 HTTP Provider 入口(为空时回退 Dummy 或 OpenAI 适配器)
- `AGENT_PROVIDER_TIMEOUT`(默认 30Provider HTTP 请求超时时间(秒)
- `AGENT_PROVIDER_CONNECT_TIMEOUT`(默认 5Provider 连接超时时间(秒)
- `AGENT_PROVIDER_RETRY_TIMES`(默认 1建立流前的重试次数仅连接失败/429/5xx 且尚未产出事件时重试)
- `AGENT_PROVIDER_RETRY_BACKOFF_MS`(默认 500重试退避毫秒指数退避
- `AGENT_OPENAI_BASE_URL`(默认 https://api.openai.com/v1OpenAI-compatible Chat Completions 基础地址
- `AGENT_OPENAI_API_KEY`OpenAI API Key为空则使用 DummyProvider
- `AGENT_OPENAI_ORGANIZATION`OpenAI Organization header可选
- `AGENT_OPENAI_PROJECT`OpenAI Project header可选
- `AGENT_OPENAI_MODEL`(默认 gpt-4o-mini模型名称
- `AGENT_OPENAI_TEMPERATURE`(默认 0.7):采样温度
- `AGENT_OPENAI_TOP_P`(默认 1.0Top-p 采样
- `AGENT_OPENAI_INCLUDE_USAGE`(默认 false是否请求流式返回 usage 统计
- `AGENT_RUN_JOB_TRIES`(默认 1AgentRunJob 队列重试次数
- `AGENT_RUN_JOB_BACKOFF`(默认 3AgentRunJob 重试退避秒数
- `AGENT_RUN_JOB_TIMEOUT`(默认 360AgentRunJob 超时时间(秒)
- 工具调用(子 Run 模式):
- `AGENT_TOOL_MAX_CALLS_PER_RUN`(默认 1单个父 Run 允许的工具调用次数上限(超过直接失败)
- `AGENT_TOOL_WAIT_TIMEOUT_MS`(默认 15000等待子 Run 写入 `tool.result` 的超时时间(毫秒)
- `AGENT_TOOL_WAIT_POLL_MS`(默认 200等待工具结果时的轮询间隔毫秒
- `AGENT_TOOL_TIMEOUT_SECONDS`(默认 15单个工具执行的预期超时时间超过会记为 TIMEOUT
- `AGENT_TOOL_RESULT_MAX_BYTES`(默认 4096工具结果最大保存字节数超出会截断
- `AGENT_TOOL_CHOICE`(默认 autoOpenAI tool_choice 传参策略
- `AGENT_TOOL_JOB_TRIES/AGENT_TOOL_JOB_BACKOFF/AGENT_TOOL_JOB_TIMEOUT`ToolRunJob 队列重试/退避/超时设置
## 🔑 API 能力一览MVP-1.1 + Archive/GetMessage/SSE
- 会话:`POST /api/sessions``GET /api/sessions`(分页/状态/关键词),`GET /api/sessions/{id}``PATCH /api/sessions/{id}`(重命名/状态CLOSED 不可重开),`POST /api/sessions/{id}/archive`幂等归档→CLOSED
- 消息:`POST /api/sessions/{id}/messages`(幂等 dedupe_keyCLOSED/LOCKED 门禁),`GET /api/sessions/{id}/messages`after_seq 增量),`GET /api/sessions/{id}/messages/{message_id}`(校验 session_id
- 实时:`GET /api/sessions/{id}/sse?after_seq=123`SSE 事件 id 为 seq`Last-Event-ID` 优先于 querygap 会回补,定期心跳保活。
- Agent Runuser.prompt 自动触发;或 `POST /api/sessions/{id}/runs {trigger_message_id}` 手动触发,写入 `run.status/agent.message`,幂等去重,失败会写 `error`(含 retryable/http_status/provider/latency_ms
详细字段/示例:`docs/ChatSession/chat-session-api.md`OpenAPI`docs/ChatSession/chat-session-openapi.yaml`。用户管理/鉴权文档:`docs/User/user-api.md`
## 🔒 状态与门禁规则
- `OPEN`:正常追加。
- `LOCKED`:拒绝 `role=USER && type=user.prompt`
- `CLOSED`:拒绝追加,例外 `role=SYSTEM && type in [run.status, error]`
- 幂等:同一 session + dedupe_key 返回已有消息(同 message_id/seqrun.status 与 agent.message 均通过 dedupe_key 防重复。
## 🔌 开发/验证
- 迁移:`docker compose exec app php artisan migrate`
- 测试:`docker compose exec app php artisan test --testsuite=Feature`
- cURL 示例(需 Bearer TOKEN
```bash
# 归档
curl -X POST http://localhost:8000/api/sessions/{sid}/archive -H "Authorization: Bearer $TOKEN"
# 单条消息
curl http://localhost:8000/api/sessions/{sid}/messages/{mid} -H "Authorization: Bearer $TOKEN"
# SSE断线续传可带 Last-Event-ID
curl -N http://localhost:8000/api/sessions/{sid}/sse?after_seq=0 \
-H "Authorization: Bearer $TOKEN" -H "Accept: text/event-stream"
```
## 📌 后续演进(规划)
- Agent Loop/Tools/Policy Engine/Context Store 解耦与插件化。
- 更丰富的前端控制台:日志流、工具审批、移动端友好。
- 兼容多家模型/工具 SDK保持开放生态。