核心结论: WorkBuddy 的工程本质不是“调模型”,而是用 Harness 工程把无状态的 LLM 变成有状态、有边界、可验证的 Agent。从入门到精通的关键,在于理解两条约束(模型无状态、知识截止)如何驱动上下文工程与权限设计的每一个决策。
模型可以抽象为一个函数:输出 = 模型(系统提示词 + 工具 + 会话历史 + 其他上下文 + 用户指令)。这个抽象携带两条硬约束:模型是无状态的,不会自动保留上一次调用的内容;模型的知识截止到训练日期,训练之后的事默认不掌握。
这两条约束决定了 WorkBuddy 所有上层工程的存在理由。对话历史、Memory、工作进度由产品侧维护状态再注入,模型本身不承担存储。入门阶段的第一课不是学 API,而是理解这个分工。
WorkBuddy 的 Loop 与常见实现类似,但没有 Harness 约束的裸 Loop 在生产环境中不可用。以下是带上下文裁剪和状态持久化的最小实现:
from dataclasses import dataclass, field
@dataclass
class HarnessedLoop:
tools: dict
max_steps: int = 20
state: dict = field(default_factory=dict)
def _trim(self, messages: list, keep_recent: int = 6) -> list:
"""上下文裁剪:保留系统提示 + 最近 N 轮"""
system = [m for m in messages if m["role"] == "system"]
recent = [m for m in messages if m["role"] != "system"][-keep_recent:]
return system + recent
def run(self, task: str) -> str:
messages = [{"role": "system", "content": "你是 WorkBuddy"},
{"role": "user", "content": task}]
for step in range(self.max_steps):
resp = llm.chat(self._trim(messages), tools=list(self.tools))
if not resp.tool_calls:
return resp.content
for tc in resp.tool_calls:
result = self.tools[tc.name](**tc.args)
self.state[f"step_{step}"] = result # 状态持久化,支持中断恢复
messages.append({"role": "tool", "content": str(result)})
return "任务未在限定步数内完成"关键区别在于 _trim 控制 token 消耗,self.state 支持跨会话延续。WorkBuddy 的 Loop 不只是一次次调模型,而是在前馈(系统提示注入)、反馈(结果验证)、权限(沙箱边界)和编排(多轮调度)的共同作用下运行。
权限边界。 WorkBuddy 的沙箱模式分三档:Read Only 只读、Workspace Write 仅工作空间可写、Full Access 无限制。以下代码在 Loop 层拦截越界操作:
from enum import Enum
class Permission(Enum):
READ_ONLY = "read_only"
WORKSPACE = "workspace"
FULL = "full"
def check_permission(mode: Permission, tool: str, args: dict) -> bool:
if mode == Permission.READ_ONLY:
return tool in ("read_file", "search", "glob")
if mode == Permission.WORKSPACE:
path = args.get("path", "")
return not path.startswith(("/etc", "C:\\Windows"))
return True结果验证。 每一步执行后检查产出是否符合预期。WorkBuddy 的 Harness 工程要求每个环节的输出能被下一环节直接使用,链路才是可反馈的环。
上下文隔离。 不同节点只看到自己需要的上下文,不携带全量对话历史。WorkBuddy 的实践表明,System Prompt 不应承载所有信息,上下文需要分层组织。
精通阶段的标志是让 Agent“长出手脚”。MCP 把“调接口”变成了“声明一个工具”。以下是一个订单查询 MCP Server 的核心实现:
from mcp.server import Server
from mcp.types import Tool, TextContent
import httpx
server = Server("order-query")
ORDER_API = "http://internal.example.com/api/orders"
@server.list_tools()
async def list_tools():
return [Tool(
name="query_order",
description="根据订单号查询状态、金额和物流",
inputSchema={"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]})]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "query_order":
async with httpx.AsyncClient() as c:
resp = await c.get(f"{ORDER_API}/{arguments['order_id']}",
timeout=10)
d = resp.json()
return [TextContent(type="text",
text=f"状态:{d['status']},金额:{d['amount']}元")]在 ~/.workbuddy/mcp.json 中注册后,Agent 即可直接调用。MCP 的核心价值在于写一次 Server,WorkBuddy、Cursor、Claude Desktop 通用。
第一,上下文是成本,不是越多越好。 每一轮对话都会把当前上下文完整发送给模型,上下文越大单轮消耗越高。保持系统提示精简、工具描述准确、历史裁剪合理。
第二,回边必须设上限。 任何可能反复执行的路径都要有 max_iterations,跑完没收敛就跳出并报告“未收敛”,而不是无限循环。
第三,权限是最后一道闸。 日常用 Workspace Write,只查不改切 Read Only,Full Access 用完立刻切回。这是 WorkBuddy 安全性设计的核心原则。
WorkBuddy 从入门到精通的分界线,不在于会调多少 API,而在于能否用 Harness 工程的约束把 Agent 从“能跑”推到“可控”。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。