跳转至

直接使用 pi-agent

examples/pi-agent-direct.ts 用成熟的 pi-agent API 实现同一个 Agent。它不是包装 本项目的 from-scratch 循环,而是直接创建 Agent、模型和 AgentTool,并复用项目的 SKILL.md loader 与通用 JSON/SQLite session store。

离线检查

npm run pi-check

这只验证 provider、模型和工具能否正确装配,不发送网络请求。

调用真实模型

npm run pi-example -- "精确计算 1234 × 5678"

示例使用 @earendil-works/pi-ai/providers/minimax-cn。如果只设置了本项目统一使用的 MINIMAX_API_KEY,示例会在进程内映射为 pi-ai 读取的 MINIMAX_CN_API_KEY

Tools、Memory 与 Skills

默认复用 AGENT_*

AGENT_TOOLS=calculator,current_time
AGENT_TOOL_EXECUTION=sequential
AGENT_MEMORY_DATABASE=.agent-data/conversations.sqlite3
AGENT_MEMORY_INDEX_DATABASE=.agent-data/memory-index.sqlite3
AGENT_SESSION_ID=pi-cli
AGENT_SKILLS_DIR=skills
AGENT_SKILLS=tool-first
AGENT_TRACE_FILE=.agent-data/traces.jsonl

需要与 from-scratch Agent 隔离时,可以使用 PI_AGENT_TOOLSPI_AGENT_MEMORY_FILEPI_AGENT_MEMORY_DATABASEPI_AGENT_MEMORY_INDEX_DATABASEPI_AGENT_SESSION_IDPI_AGENT_SKILLS_DIRPI_AGENT_SKILLS 覆盖。 工具执行策略还可以用 PI_AGENT_TOOL_EXECUTION 单独覆盖。

  • 工具通过 pi-agent 自己的 AgentTool 与 TypeBox Schema 校验;
  • 历史消息从 initialState.messages 恢复;
  • SQLite 和 JSON 都复用项目的通用 store,不依赖 pi-agent 私有存储格式;
  • agent_end listener 被 pi-agent await,memory 保存完成后 prompt() 才结束;
  • skill 仍然只注入指令,不自动获得工具或代码执行权限。
  • lifecycle listener 把 run、model 和 tool 事件写入与教学版相同的父子 span。
  • agent_start 根据最新用户消息执行相同的 Skill BM25 路由和 MemoryIndex 召回。

Timeout 与 Retry

示例的 streamFn 把下面配置直接传给 pi-ai:

AGENT_MODEL_TIMEOUT_MS=120000
AGENT_MODEL_MAX_RETRIES=1
AGENT_MAX_RETRY_DELAY_MS=8000
AGENT_RATE_LIMIT_MAX_REQUESTS=60
AGENT_RATE_LIMIT_WINDOW_MS=60000

这使用成熟库原生的 provider timeout/retry,而不是在 pi-agent 外再复制一遍 from-scratch 重试循环。

示例在 pi-agent 的 streamFn 入口复用 ModelRateLimiter,所以不同 turn 和多次 prompt() 会共享同一个平滑请求速率。pi-ai 内部 retry 仍使用它自己的退避策略。

Token / 成本预算

pi-agent 的完整 assistant message 自带标准化 usage。示例把它交给与 TypeScript 版共用的 BudgetTracker,因此仍使用同一组 AGENT_MAX_*AGENT_*_COST_* 环境变量。每次 prompt()agent_start 时重置计数;带工具调用的 turn 达到上限后,会在工具完成后 调用 pi-agent 的取消接口,不再启动下一次模型调用。

pi-ai 自身也会计算 provider cost,但本示例的成本上限只采用你显式配置的币种与单价, 避免教程把会变化的套餐价格写死。

与教学版对照

教学版 pi-agent
手写 agentLoop() Agent 内部管理循环
工具参数是普通 JSON Schema Type.Object 同时提供 Schema 与类型
自定义少量事件 标准 message/tool/agent 生命周期事件
一个 MiniMax provider pi-ai 的 provider 与 model registry
自己实现 Schema 子集 TypeBox + pi-agent 原生校验
自己实现模型重试循环 pi-ai provider 原生 timeout/retry
共用平滑限流器 streamFn 入口限制每个 turn
显式顺序/并行策略 pi-agent 原生 toolExecution
共用 BudgetTracker 原生 usage + 生命周期事件驱动预算
共用 AgentTracer 生命周期事件驱动相同的 JSONL trace

成熟库适合继续做 streaming、复杂 provider 和生产集成;教学版适合定位控制流、修改 协议以及验证自己的架构想法。

Stage 4/5 是 Agent 外层的 orchestration:pi-agent 实例可以作为 scheduler worker 或 StateGraph node,原生 lifecycle event 可转发到同一个 event bus。Graph 不复制 pi-agent 内部 loop,只负责 child 之间的任务、状态、checkpoint 与审批路径。

runPiAgentHandoff() 已把 prompt()、usage、timeout/abort 和错误统一转换成 HandoffResult。可以直接在 graph node 中调用;需要有界并发时,把多个调用函数交给 SubagentScheduler.runWorkers(),结果仍按输入顺序返回。

Stage 6 隔离评测

createPiAgent({ systemPrompt })runPiAgentHandoff(..., { systemPrompt }) 接受版本化 prompt artifact。Evaluator 可以为 baseline/candidate 分别创建新实例,读取 handoff 的输出、 token 与耗时后生成二元 EvalSampleResult。版本、holdout、gate、人工审批和发布仍由 EvolutionController 管理,pi-agent 本身不能切换 active version。

设置 AGENT_WORKSPACE_ROOT 后,示例会把同一组 workspace tools 适配成 pi-agent 的 AgentTool;仍需在 PI_AGENT_TOOLSAGENT_TOOLS 中逐个授权。Trace replay 位于 Agent 外层,所以 from-scratch 与 pi-agent 录制的完成轨迹可以进入同一个固定 dataset。

Stage 10 的 MCP 工具也先进入同一个 core ToolRegistry,再适配为 pi-agent AgentTool; 因此 AGENT_MCP_TOOLSPI_AGENT_TOOLS/AGENT_TOOLS 两层授权仍然生效。Stage 11 的 Structured Output/ModelRouter 与 Stage 12 的 DurableTaskStore 位于 Agent 外层,可包装 pi-agent 的 prompt() 或把 pi-agent handoff 注册成 durable task handler,无需复制内部 loop。

Stage 13 可以通过 AGENT_KNOWLEDGE_FILE=knowledge.json 加载带 id、title、text、uri 的 文档数组,再在 PI_AGENT_TOOLS 中选择 search_knowledge。Stage 14 的 promptPiAgentWithArtifacts() 会把同一个 ArtifactStore 中的图片适配为 pi-ai 原生 ImageContent,文本文件则作为有明确边界的文字输入。

Stage 15 通过 PI_AGENT_ROLEPI_AGENT_TENANT_IDPI_AGENT_SUBJECT 为直接调用版提供 Principal。选中的 tool、动态 Skill 和 workspace 会经过同一个 RBAC;设置这些身份变量后, memory session 也会自动按 tenant 做 SHA-256 命名空间隔离。MiniMax Key 支持 MINIMAX_API_KEY_FILE,Agent/tool 生命周期事件会写入同一个 tenant-scoped audit sink。

Stage 16 不改写 pi-agent 内部 loop。宿主先运行 GovernedMemoryBank 的证据与 replay gate, 再把 bank.active(currentTags) 作为 createPiAgent({ governedMemories }) 传入。这样 pi-agent 只看到已经激活且适用于当前任务的版本,并在 prompt 中保留原始 episode id。

Node.js 版本

当前 pi-agent 包要求 Node.js 22.19 或更高版本。