Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
defe59d
feat: implement Agent API calling with TokenKey auth
May 12, 2026
594794b
fix: convert TokenKey IIFE to proper React component to fix hooks vio…
May 12, 2026
ee191fa
fix: add Generate Key button for agents without token_key
May 12, 2026
bc38b16
fix: remove token_key Copy button — key is agent-only, not human-visible
May 12, 2026
61154d0
feat: add agent-api-calling skill + include Agent ID in relationships.md
May 12, 2026
64d4474
fix: skill references System Prompt for API URL instead of placeholder
May 12, 2026
09bd46d
fix: remove misleading 'dynamic agent ID' advice from skill
May 12, 2026
8a71a1b
feat: register agent-api-calling as default builtin skill
May 12, 2026
af6648a
feat: add tools payload debug logging to all LLM clients
May 12, 2026
3c6713b
fix: auto-retry on empty output from OpenAI Responses API reasoning m…
May 12, 2026
dd5b995
revert: remove retry logic and failover change, keep only debug logs
May 12, 2026
7030608
fix: onboarding phase never advancing — tools lost after greeting turn
May 12, 2026
597e2c5
feat(sandbox): read timeout from config instead of hardcoded 60s, all…
May 12, 2026
ead28e8
fix(sandbox): update execute_code timeout description to match config…
May 12, 2026
2c14a04
feat(sandbox): return truncated stdout and stderr even when execution…
May 12, 2026
2f30b58
feat(sandbox): add retry hint to timeout error message
May 12, 2026
c7192a3
fix(sandbox): properly capture stream output when timeout occurs
May 12, 2026
02b6746
feat(agent): forbid inline bash heredoc debugging in system prompt
May 12, 2026
ace954b
feat(agent): enhance file editing tool descriptions with strict rules
May 12, 2026
e580b20
feat: stream execute_code output to right-side Code panel in real-time
May 13, 2026
5e2a8d8
fix: handle agentbay_live events in AgentDetail.tsx to prevent ghost …
May 13, 2026
feb4dbb
fix: respect user-disabled tools in LLM payload
May 14, 2026
d95c79b
fix: skip tools without AgentTool record for configured agents
May 14, 2026
9934a3a
fix: backfill AgentTool records when tool panel is loaded
May 14, 2026
2060fd1
fix: use commit() instead of flush() for AgentTool backfill
May 14, 2026
150e09b
debug: log LLM response (content/tool_calls/reasoning) in main chat a…
May 14, 2026
a51af80
fix: reinforce finish() protocol in A2A injection
May 14, 2026
d846da0
fix: remove Focus injection from system prompt
May 14, 2026
a38ef81
feat: inject file delivery message into A2A chat session
May 14, 2026
48f5da5
fix: DetachedInstanceError in send_file_to_agent message injection
May 14, 2026
446d635
fix: correct import paths for ChatMessage/ChatSession in file deliver…
May 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ _agents/
# Internal docs
docs/
.agents/rules/deploy.md
backend/tests/test_agent_api_live.py
152 changes: 152 additions & 0 deletions backend/agent_template/skills/agent-api-calling/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
# Agent API Calling

## When to Use This Skill

当你需要通过代码(而非 `send_message_to_agent` 工具)调用其他 Agent 时使用此技能。适用场景包括:

- 在 `execute_code` 中批量调用多个 Agent 并汇总结果
- 编写自动化脚本需要跨 Agent 协作
- 需要同步等待另一个 Agent 的完整回复

> **注意:** 简单的一对一消息传递优先使用 `send_message_to_agent` 工具。API 调用适合需要在代码逻辑中嵌入 Agent 调用的场景。

---

## 所需信息的来源

你的 System Prompt 中有一个 `## Platform Agent API` 部分,其中包含:

1. **你的 Token Key** — 形如 `clw_xxxxxxxx`,用于 API 认证
2. **完整的 API 地址** — 形如 `POST https://xxx/api/v1/agent/chat`

直接从该部分复制使用即可,**不要自己拼接地址**。

---

## 如何获取目标 Agent 的 ID

你的 System Prompt 中的 `## Relationships` → `🤖 数字员工同事` 部分列出了所有可调用的 Agent:

```
### 小助手 — 数据分析助手
- Agent ID:`xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
- 关系:协作伙伴
```

从中提取 `Agent ID` 字段即可。**只有在你关系列表中的 Agent 才可以被调用。**

---

## API 调用方法

### 基本信息

- **接口地址和 Token Key:** 见你的 System Prompt 中的 `## Platform Agent API` 部分
- **认证方式:** `Authorization: Bearer <你的Token Key>`
- **超时时间:** 最长 1 小时

### Python 代码示例

```python
import requests

# ↓ 从你的 System Prompt "Platform Agent API" 部分获取这两个值
TOKEN_KEY = "clw_你的token_key"
API_URL = "https://你的平台地址/api/v1/agent/chat"

# ↓ 从你的关系网络中获取目标 Agent ID
TARGET_AGENT_ID = "目标agent的uuid"

response = requests.post(
API_URL,
headers={
"Authorization": f"Bearer {TOKEN_KEY}",
"Content-Type": "application/json",
},
json={
"agent_id": TARGET_AGENT_ID,
"prompt": "请帮我分析一下最近的销售数据趋势",
},
timeout=3600, # 最长等待1小时
)

result = response.json()
reply = result["reply"] # Agent 的回复内容
print(reply)
```

### 批量调用多个 Agent

```python
import requests
from concurrent.futures import ThreadPoolExecutor

# 从 System Prompt 获取
TOKEN_KEY = "clw_你的token_key"
API_URL = "https://你的平台地址/api/v1/agent/chat"

HEADERS = {
"Authorization": f"Bearer {TOKEN_KEY}",
"Content-Type": "application/json",
}

# 从关系网络中获取的 Agent 列表
tasks = [
{"agent_id": "agent-uuid-1", "prompt": "分析销售数据"},
{"agent_id": "agent-uuid-2", "prompt": "生成周报摘要"},
{"agent_id": "agent-uuid-3", "prompt": "检查库存预警"},
]

def call_agent(task):
resp = requests.post(API_URL, headers=HEADERS, json=task, timeout=3600)
return {"agent_id": task["agent_id"], "reply": resp.json()["reply"]}

# 并行调用
with ThreadPoolExecutor(max_workers=3) as pool:
results = list(pool.map(call_agent, tasks))

for r in results:
print(f"Agent {r['agent_id']}: {r['reply'][:100]}...")
```

---

## 响应格式

```json
{
"reply": "Agent 的完整回复文本",
"usage": {}
}
```

---

## 错误处理

| HTTP 状态码 | 含义 | 处理方式 |
|---|---|---|
| 401 | Token Key 无效或缺失 | 检查 Authorization header |
| 403 | 无权调用(不在关系列表中,或目标已过期) | 确认目标 Agent 在你的关系网络中 |
| 404 | 目标 Agent 不存在 | 检查 Agent ID 是否正确 |
| 400 | 目标 Agent 未配置 LLM 模型 | 联系管理员配置模型 |
| 422 | 请求参数错误(如 prompt 为空) | 检查请求体格式 |
| 502 | LLM 调用失败 | 重试或联系管理员 |

```python
response = requests.post(API_URL, headers=HEADERS, json=payload, timeout=3600)
if response.status_code != 200:
print(f"调用失败: {response.status_code} - {response.json().get('detail', '')}")
else:
print(response.json()["reply"])
```

---

## What NOT to Do

- 不要自己拼接 API 地址,从 System Prompt 的 `Platform Agent API` 部分直接获取
- 不要调用不在你关系列表中的 Agent,会返回 403
- 不要在日志或回复中暴露你的 Token Key
- 不要设置过短的超时时间,复杂任务可能需要较长处理时间
- 对于简单的一对一对话,优先使用 `send_message_to_agent` 工具而不是 API
28 changes: 28 additions & 0 deletions backend/alembic/versions/add_agent_token_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Add token_key fields to agents table for Agent API calling.

Revision ID: add_agent_token_key
Revises: None (standalone — depends on current head)
"""

from alembic import op
import sqlalchemy as sa


# revision identifiers
revision = "add_agent_token_key"
down_revision = None # Will be set by Alembic chain
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Chain new Alembic revision to existing migration head

Set down_revision to the current head instead of None; this file currently creates a second base revision, so environments already stamped to the existing chain will not have a valid upgrade path to this migration. In practice this can block alembic upgrade in deployed databases until the revision graph is manually repaired.

Useful? React with 👍 / 👎.

branch_labels = None
depends_on = None


def upgrade():
op.add_column("agents", sa.Column("token_key", sa.String(128), nullable=True, index=True))
op.add_column("agents", sa.Column("token_key_suffix", sa.String(4), nullable=True))
# Create index explicitly for the token_key lookup
op.create_index("ix_agents_token_key", "agents", ["token_key"], unique=False)


def downgrade():
op.drop_index("ix_agents_token_key", table_name="agents")
op.drop_column("agents", "token_key_suffix")
op.drop_column("agents", "token_key")
Loading