187 lines
6.6 KiB
Markdown
187 lines
6.6 KiB
Markdown
|
|
# 创建Agent经验总结(实战版)
|
|||
|
|
|
|||
|
|
> 基于本仓库实际落地的 **Android应用开发助手**(已发布可用)沉淀:从“想法→工作流→落库→发布→验证→避坑”一套流程。
|
|||
|
|
|
|||
|
|
## 1. 目标与验收标准
|
|||
|
|
|
|||
|
|
- **目标**:在 Agent 管理页面出现一个“可运行/可使用”的 Agent,并且能通过 `/api/v1/executions` 正常触发执行并拿到结果。
|
|||
|
|
- **关键验收**:
|
|||
|
|
- **状态**:Agent 为 `published` 或 `running`(否则普通用户无法执行)
|
|||
|
|
- **工作流**:`workflow_config` 必须包含合法的 `nodes` / `edges`,能从 `start` 走到 `end`
|
|||
|
|
- **数据链路**:LLM prompt 能正确拿到用户输入(一般是 `{{query}}` / `{{user_query}}`)
|
|||
|
|
|
|||
|
|
## 2. 两种创建方式:UI vs 脚本
|
|||
|
|
|
|||
|
|
### 2.1 UI 创建(适合调试)
|
|||
|
|
|
|||
|
|
- 优点:所见即所得、方便调整 prompt/连线/节点参数
|
|||
|
|
- 缺点:重复劳动多,不利于批量/版本化
|
|||
|
|
|
|||
|
|
### 2.2 脚本创建(推荐用于“生成一批可运行Agent/一键复现”)
|
|||
|
|
|
|||
|
|
- 典型做法:写一个 `backend/scripts/generate_xxx_agent.py`,直接用 SQLAlchemy 创建或更新 Agent。
|
|||
|
|
- 本仓库示例:
|
|||
|
|
- `backend/scripts/generate_android_agent.py`(Android应用开发助手)
|
|||
|
|
- `backend/scripts/generate_content_agent.py`(内容生成助手)
|
|||
|
|
|
|||
|
|
## 3. Agent 能不能“运行”,最关键的规则
|
|||
|
|
|
|||
|
|
### 3.1 Agent 状态与执行权限
|
|||
|
|
|
|||
|
|
后端创建执行时会做状态校验:**非 owner 执行必须是 `published/running`**。
|
|||
|
|
|
|||
|
|
对应代码(要点:状态不对会 403):
|
|||
|
|
|
|||
|
|
```103:104:backend/app/api/executions.py
|
|||
|
|
if agent.status not in ["published", "running"] and agent.user_id != current_user.id:
|
|||
|
|
raise HTTPException(status_code=403, detail="Agent未发布或无权执行")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**经验**:
|
|||
|
|
- 如果你希望“创建出来立刻可用”,脚本里就直接写 `status="published"`。
|
|||
|
|
- 如果你希望“先草稿”,脚本里写 `draft`,但要用 owner 测试或再部署发布。
|
|||
|
|
|
|||
|
|
### 3.2 workflow_config 的最低要求
|
|||
|
|
|
|||
|
|
- 必须包含:
|
|||
|
|
- `nodes`: 节点数组
|
|||
|
|
- `edges`: 连线数组
|
|||
|
|
- 且能通过校验(创建接口会校验):
|
|||
|
|
- 参考:`backend/app/api/agents.py` 中 `create_agent` 会调用 `validate_workflow(...)`
|
|||
|
|
|
|||
|
|
**经验**:
|
|||
|
|
- 最小可运行工作流:`start -> llm -> end`
|
|||
|
|
- 复杂工作流建议:`start -> 分析(llm) -> 分流(condition) -> 子分支(llm/transform) -> 汇总(transform) -> 输出优化(llm) -> end`
|
|||
|
|
|
|||
|
|
## 4. 数据流转与 Prompt 设计(决定“是否答非所问”)
|
|||
|
|
|
|||
|
|
### 4.1 输入字段命名建议
|
|||
|
|
|
|||
|
|
本平台执行 Agent 时,常见输入会放在:
|
|||
|
|
- `query`
|
|||
|
|
- `USER_INPUT`
|
|||
|
|
|
|||
|
|
Android 示例项目也是这样发起的:
|
|||
|
|
- `query = 用户输入`
|
|||
|
|
- `USER_INPUT = 用户输入`
|
|||
|
|
|
|||
|
|
**经验**:
|
|||
|
|
- prompt 里优先用 `{{query}}`(平台链路更稳定)
|
|||
|
|
- 如果你做了 transform 映射,可统一成 `user_query` 再用 `{{user_query}}`
|
|||
|
|
|
|||
|
|
### 4.2 先分析、再生成:降低跑偏
|
|||
|
|
|
|||
|
|
常见稳定结构:
|
|||
|
|
- 第 1 个 LLM:**需求抽取/结构化**(JSON 输出)
|
|||
|
|
- 后续 LLM:拿着“结构化需求 + 原始需求”做生成/诊断/优化
|
|||
|
|
|
|||
|
|
这样可以显著减少“答非所问”,也便于条件分支与 transform 做数据拼接。
|
|||
|
|
|
|||
|
|
## 5. 条件分支的关键坑:`sourceHandle`
|
|||
|
|
|
|||
|
|
条件节点“走哪个分支”,靠 edge 的 `sourceHandle` 来区分(例如 `true` / `false`)。
|
|||
|
|
|
|||
|
|
对应引擎逻辑(要点:**只保留 sourceHandle == branch 的边**):
|
|||
|
|
|
|||
|
|
```1936:1961:backend/app/services/workflow_engine.py
|
|||
|
|
if node.get('type') == 'condition':
|
|||
|
|
branch = result.get('branch', 'false')
|
|||
|
|
# 只保留:不是从条件节点出发的边,或 从条件节点出发且sourceHandle匹配分支的边
|
|||
|
|
edges_to_remove = []
|
|||
|
|
edges_to_keep = []
|
|||
|
|
for edge in active_edges:
|
|||
|
|
if edge['source'] == next_node_id:
|
|||
|
|
edge_handle = edge.get('sourceHandle')
|
|||
|
|
if edge_handle == branch:
|
|||
|
|
edges_to_keep.append(edge)
|
|||
|
|
else:
|
|||
|
|
edges_to_remove.append(edge)
|
|||
|
|
else:
|
|||
|
|
edges_to_keep.append(edge)
|
|||
|
|
active_edges = edges_to_keep
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**经验**:
|
|||
|
|
- 条件节点的出边必须带 `sourceHandle`,而且值要与引擎产出的 `branch` 完全一致(常用:`true`/`false`)
|
|||
|
|
- 否则会出现:
|
|||
|
|
- 分支全跑 / 分支全不跑 / 走错分支
|
|||
|
|
|
|||
|
|
## 6. 用脚本创建“可运行Agent”的推荐模板
|
|||
|
|
|
|||
|
|
核心点:
|
|||
|
|
- 查用户(owner)
|
|||
|
|
- 构造 `nodes/edges`
|
|||
|
|
- 若同名存在则更新,否则创建
|
|||
|
|
- 设置 `status="published"`
|
|||
|
|
|
|||
|
|
本仓库可直接复用(已验证创建成功):
|
|||
|
|
- `backend/scripts/generate_android_agent.py`
|
|||
|
|
|
|||
|
|
运行方式:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd /home/renjianbo/aiagent
|
|||
|
|
python3 backend/scripts/generate_android_agent.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
运行后会输出 Agent ID、节点数、边数,且状态为 `published`。
|
|||
|
|
|
|||
|
|
## 7. 如何验证 Agent “真的可运行”
|
|||
|
|
|
|||
|
|
### 7.1 前端验证
|
|||
|
|
|
|||
|
|
- 进入 **Agent管理**
|
|||
|
|
- 找到 Agent(例如:Android应用开发助手)
|
|||
|
|
- 状态为 **已发布/运行中**
|
|||
|
|
- 点击 **使用**,输入一句话触发执行
|
|||
|
|
|
|||
|
|
### 7.2 API 验证(推荐可自动化)
|
|||
|
|
|
|||
|
|
1) 登录获取 token(form-urlencoded)
|
|||
|
|
2) 发起执行:
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
POST /api/v1/executions
|
|||
|
|
{
|
|||
|
|
"agent_id": "你的agent_id",
|
|||
|
|
"input_data": {
|
|||
|
|
"query": "帮我生成一个登录页",
|
|||
|
|
"USER_INPUT": "帮我生成一个登录页"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3) 轮询状态:
|
|||
|
|
- `GET /api/v1/executions/{execution_id}/status`
|
|||
|
|
4) 获取结果:
|
|||
|
|
- `GET /api/v1/executions/{execution_id}`
|
|||
|
|
|
|||
|
|
## 8. 常见问题与排查清单
|
|||
|
|
|
|||
|
|
- **Agent 列表里看到了,但点“使用”无权限/403**
|
|||
|
|
- 检查 `status` 是否为 `published/running`
|
|||
|
|
- 是否为 owner 在测试草稿
|
|||
|
|
|
|||
|
|
- **LLM 输出跑偏/答非所问**
|
|||
|
|
- 是否把用户输入稳定透传到了 `{{query}}`
|
|||
|
|
- 是否先做“需求结构化”再生成
|
|||
|
|
- prompt 是否过泛、缺少输出格式约束
|
|||
|
|
|
|||
|
|
- **条件节点后续分支乱跑**
|
|||
|
|
- 检查条件节点出边是否有 `sourceHandle=true/false`
|
|||
|
|
- 检查引擎分支值是否与 sourceHandle 对齐
|
|||
|
|
|
|||
|
|
- **输出结构混乱**
|
|||
|
|
- 建议末端增加 `llm-format` 做统一 Markdown 格式化
|
|||
|
|
- end 节点尽量只输出最终 `output` 字段(不要拼接用户 query)
|
|||
|
|
|
|||
|
|
## 9. 本次落地成果(可复用资产)
|
|||
|
|
|
|||
|
|
- **可运行 Agent**:Android应用开发助手(脚本创建,状态 `published`)
|
|||
|
|
- **生成脚本**:`backend/scripts/generate_android_agent.py`
|
|||
|
|
- **Prompt 方案文档**:`androidExampleDemo/多功能android应用智能体的提示词.md`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
最后更新:2026-01-20
|