Agent 开发岗这两年从“听起来很玄”变成了招聘 JD 里实打实的一栏工具调用、任务编排、记忆管理、评测回归、可观测性一条都躲不开。很多人卡住的地方不是不会调 API而是不知道该把一个 Agent 拆成哪几层、每层用什么方案验证、面试官追问“你的 Agent 为什么这么设计”时说不出取舍理由。这篇就把这条链路从零到跑通讲清楚重点放在能落地的代码结构和验证方法上而不是概念堆叠。本文会围绕一条主线展开先手写一个最小 Agent Loop把“模型—工具—观察结果—再决策”的闭环跑通再往上加工具调用规范、记忆压缩、规划分层然后用 Harness 把 Agent 当成软件来跑回归测试最后做服务化封装、批量任务和成本观察。这里面 DeepAgent 可以理解为面向长链路深度任务的编排方式Harness 则是把模型、工具、权限、日志、判分包在一起的运行外壳两者一个管“跑得远”一个管“测得准”。硬件门槛其实不高。真正跑通一个 Agent 循环一块能带动 7B 到 14B 量级模型的消费级显卡就够做本地联调甚至只做工具编排和流程验证时直接调远程推理接口、本地只跑业务代码也完全可行。真正吃资源的是评测环节和长上下文场景批量跑几百条任务、每条轨迹几十轮Token 消耗和并发压力会比单次对话高一个数量级这部分才是需要提前规划的。下面的内容适合三类读者准备转 Agent 方向、想知道面试到底考什么的开发者已经在写业务代码、想把 LLM 接进现有系统但不清楚工程边界的后端同学以及搭过 Demo、但一上量就崩、想知道怎么补评测和可观测性的同学。全程给可复制的代码模板路径、模型名、端口按你自己的环境替换即可。1. Agent 开发岗核心能力速览先给一张能力表把 Agent 岗真正考察的东西摆出来。这张表不是让你背而是让你对照自己的短板决定学习顺序如果你连 Function Calling 的参数校验都没写过就别急着上多智能体如果你没跑过任何评测集面试聊“效果好不好”基本会被问穿。能力项具体内容掌握标准优先级Agent 循环决策、工具调用、结果回填、终止条件能不看文档手写 while 循环最高工具调用JSON Schema 定义、参数校验、错误回传能处理工具抛错和非法参数最高上下文管理裁剪、摘要压缩、Token 预算长对话不崩、不丢关键信息高规划能力ReAct、Plan-and-Execute、任务分解能解释两种范式的取舍高记忆系统短期会话、长期向量库、结构化状态能设计读写时机与失效策略中高多智能体编排者-执行者、Handoff、并行分发能说清什么时候不该用中Harness 评测任务集、判分器、轨迹记录、回归能跑出可对比的通过率高服务化流式输出、超时、重试、幂等能扛住并发和断连高安全边界提示注入防护、权限最小化、沙箱高危工具有人工确认高成本与性能Token 统计、P95 延迟、调用次数能给出优化前后对比中高表格里有几个点值得单独强调。第一Agent 循环是整个岗位的地基市面上所有框架不管是哪家的编排库底层都是同一个模式把对话历史发给模型模型返回要么是最终答案、要么是工具调用请求执行工具后把结果作为新消息塞回历史再发一次。理解这一点之后框架就只是语法糖你随时可以自己写一个。第二评测能力是被严重低估的一项很多候选人能做出 Demo但说不出“我的改版让通过率从 62% 提到 78%”这在面试里是很致命的空缺。第三安全边界不是加分项而是底线只要你的 Agent 能执行 shell、能读写文件、能发起网络请求就必须回答清楚权限怎么控。再补一句关于“深度任务”的理解。长链路任务和普通问答的差别在于错误会累积单步 95% 正确率二十步之后就只剩 36%。所以 DeepAgent 这类深度编排思路的核心不是让模型更聪明而是通过子任务拆分、中间结果校验、失败重规划把长链路的误差控制住。你如果能把这句逻辑讲明白比会背十个框架名有用得多。2. 适用人群、能力分级与使用边界Agent 开发不是一个独立工种它是后端能力加模型理解的交叉。从招聘要求看绝大多数岗位默认你已经会写服务、懂接口、能看日志然后再加一层 LLM 相关的知识。所以学习路径不应该从“提示词技巧”开始而应该从“怎么把一个不确定输出的组件塞进确定的工程流程”开始。这也是为什么很多人学了一堆提示词模板真上手做项目还是无从下手。按能力可以粗分三级。入门级是能调通 API、写一个带两三个工具的 Agent、处理基本异常这个阶段一到两周能到重点是手熟。进阶级是能设计状态机、做上下文压缩、接 RAG、跑一套评测集并且能解释每个设计选择的代价这个阶段通常需要完整做完一个项目。高级是能做多智能体编排、做权限隔离和沙箱、把成本和延迟压到业务可接受的范围并且能主导技术选型这部分靠项目量堆出来光看资料到不了。需要明确的边界也不少。第一Agent 不是万能的任务如果步骤固定、输入格式稳定用传统代码加规则就够了硬套 Agent 只会让系统更难调试、更贵、更慢。第二涉及自动化操作的能力必须限定范围文件写入限制在指定目录、命令执行放在容器里、网络请求走白名单任何“能删能改”的工具都要有人工确认或 dry-run 模式。第三涉及个人数据、账号凭证、商业机密的场景要么本地部署要么明确数据处理协议日志里不要落明文密钥。还有一层合规提醒必须写清楚如果你的 Agent 要处理人脸、声音、证件、合同、医疗记录这类敏感素材必须确认素材来源合法、当事人授权明确输出内容也要有审核环节。做内容生成类 Agent 时批量产出不等于可以批量发布人工复核这一步不能省。技术能力越强越要在设计阶段就把这些约束写进流程而不是等出问题再补。3. 环境准备与工程脚手架环境这块不用搞得太重。做 Agent 开发绝大部分时间花在写业务逻辑和调试 Prompt 上真正吃显卡的只有本地推理那一段。所以最优解是双轨本地跑业务代码和评测脚本模型走远程推理服务或者本地小模型只有在需要压测、需要断网环境、需要控制数据不出域的时候才把模型拉到本地。这样迭代速度最快也不会被显存卡住。基础环境建议统一到 Python 3.10 或 3.11虚拟环境用 venv 或 conda 都行关键是每个项目独立别把不同项目的依赖混在一起。核心依赖不多模型 SDK、HTTP 客户端、参数校验库、Web 框架、评测用的数据处理库。下面是一份通用安装模板版本号不写死按你实际环境锁定即可。# 创建并激活虚拟环境 python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate # 安装通用依赖版本按项目锁文件为准 pip install -U openai pydantic httpx fastapi uvicorn python-dotenv # 可选本地推理与向量检索 pip install -U sentence-transformers faiss-cpu目录结构建议一开始就分好别等到文件堆成垃圾场再重构。输入素材、Prompt 模板、工具实现、评测任务集、运行日志、输出结果这六类东西生命周期完全不同混在一个目录里后期排错会非常痛苦。agent-project/ ├── configs/ # 模型配置、工具开关、超时参数 ├── prompts/ # 系统提示词、子任务提示词模板 ├── tools/ # 每个工具一个文件含 schema 与实现 ├── core/ # agent loop、记忆、规划器 ├── eval/ │ ├── tasks.jsonl # 评测任务集 │ ├── graders/ # 判分器 │ └── reports/ # 跑批结果 ├── logs/ # 轨迹日志按 run_id 分目录 └── app.py # 服务入口配置文件里只放不会频繁变的东西模型名、温度、最大轮数、单步超时、Token 预算上限这些集中管理方便做 A/B 对比。特别提醒一点把所有跟模型相关的参数放进配置而不是硬编码在代码里因为你要做评测对比时唯一变量原则非常重要改一个参数跑一次才能知道是谁带来的提升。{ model: your-model-name, base_url: http://127.0.0.1:8000/v1, temperature: 0.2, max_steps: 12, step_timeout_sec: 60, max_context_tokens: 24000, tool_retry: 1, log_dir: ./logs }max_steps这个参数一定要设。没有步数上限的 Agent 是灾难遇到死循环会一直烧 Token跑批的时候一晚上能把预算跑光。step_timeout_sec同理某个工具卡住不返回时超时中断比无限等待优雅得多。这两个参数看着不起眼是新手和老手最明显的分水岭之一。4. 手写 Agent Loop从零跑通一个最小智能体这一节是整篇文章的核心。不管后面用什么框架这个循环你必须能默写出来。逻辑只有四步拼消息、调模型、判断是否有工具调用、执行工具并把结果塞回消息列表。终止条件也很简单模型返回纯文本答案或者达到最大轮数或者触发人工中断。先看一个不依赖任何编排框架的最小实现。它用的是 OpenAI 兼容的接口格式绝大多数本地推理服务和云端服务都支持这套协议把base_url和model换成你自己的即可。# core/agent_loop.py import json import time from typing import Any from openai import OpenAI client OpenAI(base_urlhttp://127.0.0.1:8000/v1, api_keyEMPTY) def run_agent( user_input: str, tools_schema: list[dict], tool_impl: dict[str, Any], system_prompt: str 你是一个严谨的助手必要时调用工具不要臆造事实。, max_steps: int 12, ) - dict: messages: list[dict] [ {role: system, content: system_prompt}, {role: user, content: user_input}, ] trace: list[dict] [] for step in range(max_steps): started time.time() resp client.chat.completions.create( modelyour-model-name, messagesmessages, toolstools_schema if tools_schema else None, temperature0.2, ) msg resp.choices[0].message trace.append({ step: step, latency_ms: int((time.time() - started) * 1000), content: msg.content, tool_calls: [tc.model_dump() for tc in (msg.tool_calls or [])], }) # 没有工具调用 模型给出最终答案循环结束 if not msg.tool_calls: return {answer: msg.content, trace: trace, steps: step 1} # 把模型这一轮的决策写回历史 messages.append({ role: assistant, content: msg.content or , tool_calls: [tc.model_dump() for tc in msg.tool_calls], }) # 逐个执行工具结果以 tool 角色回填 for tc in msg.tool_calls: name tc.function.name raw_args tc.function.arguments or {} try: args json.loads(raw_args) if name not in tool_impl: raise KeyError(f未注册的工具: {name}) result tool_impl[name](**args) content json.dumps(result, ensure_asciiFalse) except Exception as exc: # 关键错误要回传给模型而不是直接抛出 content json.dumps({error: str(exc)}, ensure_asciiFalse) messages.append({ role: tool, tool_call_id: tc.id, content: content, }) return {answer: None, trace: trace, steps: max_steps, reason: max_steps_reached}这段代码有几个细节值得反复看。第一异常必须被捕获并以字符串形式回传给模型这是 Agent 自愈能力的基础。你把异常直接抛出去服务就挂了回传给模型模型有机会换个参数重试或者换条路走。第二每条工具结果都要带tool_call_id这是协议要求丢了模型会报错。第三trace 一定要记它是你后面做评测、做复盘、做面试展示的唯一凭证没有轨迹的 Agent 等于黑盒。判断这个循环跑通的标准很简单给它一个必须用工具才能回答的问题比如“查询当前目录下有多少个 markdown 文件”看它是否先调用列表工具再给答案。如果模型直接编一个数字出来说明系统提示词约束不够或者工具描述写得不够清楚。常见失败原因有三个工具 schema 里description太含糊、模型本身指令遵循能力弱、温度设太高导致不稳定。5. 工具调用与 Function Calling 实战工具定义写得好不好直接决定 Agent 的上限。很多人写 schema 只写个名字和参数类型模型根本不知道什么时候该用于是要么不调用要么乱调用。写 tool 描述的原则是说清楚它做什么、说清楚什么时候用、说清楚参数格式最好再给一个反例说明什么情况下不要用。# tools/file_tools.py import os SAFE_ROOT os.path.abspath(./workspace) def list_files(path: str ., pattern: str ) - dict: 列出指定目录下的文件。path 必须是 SAFE_ROOT 的子路径。 target os.path.abspath(os.path.join(SAFE_ROOT, path)) if not target.startswith(SAFE_ROOT): raise PermissionError(路径越界拒绝访问) if not os.path.isdir(target): raise NotADirectoryError(f不是目录: {path}) items [] for name in sorted(os.listdir(target)): if pattern and pattern not in name: continue full os.path.join(target, name) items.append({name: name, is_dir: os.path.isdir(full), size: os.path.getsize(full) if os.path.isfile(full) else None}) return {count: len(items), items: items[:50]} LIST_FILES_SCHEMA { type: function, function: { name: list_files, description: ( 列出指定目录下的文件和子目录。 适用场景用户询问某个目录里有什么、有多少文件、文件大小。 不适用读取文件内容请用 read_file、搜索文件内容请用 grep_text。 path 只能是相对路径且必须位于工作区内。 ), parameters: { type: object, properties: { path: {type: string, description: 相对路径默认当前目录}, pattern: {type: string, description: 文件名包含的关键字可留空}, }, required: [], }, }, }这里有两个工程上的硬要求。第一路径校验必须写在工具内部不能指望模型遵守提示词。模型被骗的成本很低你把../../etc这类输入交给它迟早会有人试。第二返回结果要有上限items[:50]就是限制不然一个大目录塞进上下文几万 Token 下去后面的推理全废了。这类“返回截断 分页提示”的设计是 Agent 工具工程里最容易被忽略的细节。参数校验建议用 Pydantic 再包一层。模型生成的 JSON 经常出现类型错误比如该传数组传成字符串、该传数字传成 “3”。用 Pydantic 做一层强校验校验失败就把错误信息当成工具结果回传模型通常下一轮就能改对。这套“校验失败 → 错误回传 → 模型自修正”的机制是提升 Agent 稳定性的性价比最高的一招比换更大的模型还管用。工具数量也要控制。一次性暴露二三十个工具模型的选错率会明显上升。经验做法是分组主控 Agent 只拿五到八个高频工具其余工具通过子 Agent 或者“工具检索”的方式按需挂载。如果你的项目工具特别多可以先用一次轻量的模型调用做工具路由把候选集缩到三五个再进主循环这样既能保住能力又能压住错误率。6. 记忆、规划与深度任务编排上下文管理是 Agent 从 Demo 走向可用的第二道坎。对话一长消息列表就会膨胀成本上升、延迟上升更麻烦的是模型注意力被稀释前面说过的约束记不住了。解决办法不是简单地砍历史而是分层最近几轮原文保留较早的对话做摘要压缩关键事实抽成结构化状态单独存长期知识放向量库按需检索。摘要压缩的触发时机要看 Token 预算而不是轮数。下面这段是通用模板接入你实际的 tokenizer 即可核心逻辑是“超过阈值就压压完要验证关键信息没丢”。# core/memory.py def maybe_compress(messages, count_tokens, threshold18000, keep_recent6): 超出预算时把中间历史压成摘要保留系统提示与最近若干轮。 total count_tokens(messages) if total threshold or len(messages) keep_recent 2: return messages, None system_part [m for m in messages if m[role] system] recent messages[-keep_recent:] middle [m for m in messages if m[role] ! system and m not in recent] # 这里的摘要调用建议用小模型或低温度保证稳定且便宜 summary_prompt ( 把下面的对话压缩成要点列表保留用户目标、已确认的事实、 已失败的方法、待办事项。不要编造不要省略数字和路径。\n\n \n.join(f{m[role]}: {m.get(content) or } for m in middle) ) summary call_small_model(summary_prompt) compressed system_part [ {role: system, content: 历史对话摘要如下\n summary} ] recent return compressed, summary规划这块ReAct 和 Plan-and-Execute 是必答的两种范式。ReAct 是边想边做每步根据观察结果调整适合步骤不确定、需要探索的任务Plan-and-Execute 是先出完整计划再逐步执行适合步骤清晰、可以并行的任务。前者灵活但容易跑偏后者高效但计划一旦出错就全盘皆输所以实践中常见的是混合先出粗略计划执行中允许重规划每个子任务内部用 ReAct。深度任务编排的关键在于把长链路切成短链路。一个二十步的任务如果一次性交给模型中间任何一步幻觉都会传染切成五个四步的子任务每个子任务独立验收出错只回滚一段。这就是 DeepAgent 这类思路的价值所在它不追求单步能力提升而是通过任务分解、中间产物检查点、失败重试把累积误差压下来。工程上你可以用一个简单状态机来实现每个子任务有明确的输入契约和输出契约验收不过就重跑该子任务而不是整个流程重来。长期记忆要谨慎。向量库检索看起来很美实际很容易引入无关内容污染上下文。建议只在两类场景开一是用户画像、偏好这类跨会话稳定信息二是知识库问答这类有明确来源的检索。写入策略上不要每轮都写让模型输出一个明确的“值得记住”的判断再落库同时在检索时带上相似度阈值低于阈值宁可不召回。7. Harness 评测体系把 Agent 当软件来测这是拉开差距的一章。绝大多数人做 Agent 的做法是改一版提示词手动试五六个输入感觉不错就上线。这种做法的问题在于不可复现你不知道这次提升是提示词带来的还是模型更新带来的也不知道改完之后哪些原本能过的 case 挂了。Harness 的存在就是为了解决这个问题它把任务集、运行器、判分器、报告四件套固定下来每次改动跑一遍用通过率说话。任务集的构造要点是覆盖面而不是数量。一个实用的起步规模是五十到一百条按能力维度分层单工具任务、多工具串联、需要拒答的任务、需要多轮澄清的任务、容易触发幻觉的任务、边界输入空值、超长、特殊字符。每条任务写清输入、期望结果类型、判分方式。别一开始就追求几千条先把判分逻辑跑顺。{ task_id: single_tool_001, category: single_tool, input: 工作区里有多少个 markdown 文件, expect: { must_call_tools: [list_files], answer_contains: [个], max_steps: 4 }, grader: rule }运行器的核心是不让一条失败拖垮整批。要设置单条超时、并发上限、失败重试次数并且把每条任务的完整轨迹落盘方便事后回看是哪一步跑偏的。下面是一个可复用的跑批模板agent_fn就是前面那个循环包一层。# eval/run_harness.py import json, time, traceback from concurrent.futures import ThreadPoolExecutor, as_completed def load_tasks(path./eval/tasks.jsonl): with open(path, encodingutf-8) as f: return [json.loads(line) for line in f if line.strip()] def grade(task, result): exp task.get(expect, {}) called {tc[function][name] for step in result.get(trace, []) for tc in (step.get(tool_calls) or [])} missing set(exp.get(must_call_tools, [])) - called answer result.get(answer) or hits [kw for kw in exp.get(answer_contains, []) if kw in answer] passed (not missing) and len(hits) len(exp.get(answer_contains, [])) return {passed: passed, missing_tools: list(missing), answer_matched: hits, steps: result.get(steps)} def run_all(tasks, agent_fn, concurrency4, retry1): report [] def one(t): last_err None for _ in range(retry 1): try: res agent_fn(t[input]) return {task_id: t[task_id], **grade(t, res), error: None} except Exception as exc: last_err traceback.format_exc(limit2) return {task_id: t[task_id], passed: False, error: str(last_err)} with ThreadPoolExecutor(max_workersconcurrency) as pool: futures {pool.submit(one, t): t for t in tasks} for fut in as_completed(futures): report.append(fut.result()) total len(report) passed sum(1 for r in report if r[passed]) return {total: total, passed: passed, pass_rate: round(passed / total, 4) if total else 0, details: report} if __name__ __main__: tasks load_tasks() result run_all(tasks, lambda q: {answer: 占位, trace: []}) print(json.dumps({k: v for k, v in result.items() if k ! details}, ensure_asciiFalse, indent2))规则判分能覆盖六七成场景剩下的开放性问题需要 LLM 判分。用模型判分要注意三点一是判分提示词要把评分标准和输出格式写死只输出通过或不通过加理由二是判分模型最好和被测模型不同源避免自我偏袒三是要定期人工抽查判分结果校准漂移。判分的稳定性比判分的精细度更重要一个总是给出模棱两可结论的判分器会让整个评测体系失去意义。跑出报告之后要形成习惯每次改动都记一条记录包含改动内容、通过率、平均步数、平均 Token 消耗、P95 延迟。这几项一起看才能避免“通过率涨了但成本翻三倍”这种隐性退化。面试时能拿出这样一份曲线比说十句“我对 Agent 有深入理解”有说服力。8. 接口服务化、批量任务与资源成本观察Agent 最终要接进业务就得服务化。最常见的形态是一个 HTTP 接口接收用户输入内部跑 Agent 循环把过程以流式方式吐出来。流式很重要因为 Agent 一次任务可能要几十秒没有中间反馈用户会以为卡死了。下面是一个最小可运行的 FastAPI 骨架重点看超时控制、并发限流和会话隔离这三块。# app.py import asyncio, uuid from fastapi import FastAPI, HTTPException from fastapi.responses import StreamingResponse from pydantic import BaseModel, Field app FastAPI(titleAgent Service) SEMAPHORE asyncio.Semaphore(4) # 全局并发上限按显存/额度调整 class AskRequest(BaseModel): query: str Field(min_length1, max_length4000) session_id: str | None None max_steps: int Field(default10, ge1, le20) app.post(/v1/agent/run) async def run(req: AskRequest): session_id req.session_id or uuid.uuid4().hex if SEMAPHORE.locked() and SEMAPHORE._value 0: raise HTTPException(status_code429, detail服务繁忙请稍后重试) async with SEMAPHORE: try: result await asyncio.wait_for( asyncio.to_thread(run_agent, req.query, [], {}, max_stepsreq.max_steps), timeout180, ) except asyncio.TimeoutError: raise HTTPException(status_code504, detail任务超时请缩小问题范围) return {session_id: session_id, **result} app.get(/v1/agent/stream) async def stream(q: str): async def gen(): for chunk in [正在分析问题..., 正在调用工具..., 已生成答案]: yield fdata: {chunk}\n\n await asyncio.sleep(0.3) return StreamingResponse(gen(), media_typetext/event-stream)部署命令很普通关键是别把调试模式开到生产# 开发调试 uvicorn app:app --host 127.0.0.1 --port 7860 --reload # 生产启动关闭 reload限制 worker 数避免显存被多进程打爆 uvicorn app:app --host 0.0.0.0 --port 7860 --workers 1 --timeout-keep-alive 75批量任务和在线接口要分开部署。批量场景的特点是允许排队、允许慢、但要求不丢任务所以要用队列加状态落盘而不是简单并发。每条任务记录task_id、状态、重试次数、最后一次错误进程重启后能从断点续跑。并发数不要拍脑袋定先测单条任务的平均耗时和峰值显存再倒推能承受的并发超过了就排队别硬扛。成本观察要落到指标上。至少盯这几个单任务平均 Token 消耗、平均工具调用次数、P95 延迟、失败率、超时率、人均重试次数。工具调用次数是个很灵敏的指标它突然上涨通常意味着提示词约束松了或者工具描述不清楚模型在瞎试。Token 消耗突增则常见于上下文压缩失效或者工具返回结果没做截断。把这些指标接到监控上比事后翻日志高效得多。9. 常见问题与排查方法Agent 的坑集中在几类跑不通、跑不稳、跑不准、跑太贵。下面这张表覆盖了实际开发中最常撞见的问题按现象去找原因基本能定位到七八成。问题现象可能原因排查方式解决方案模型从不调用工具工具描述含糊、提示词没约束打印请求体检查 tools 是否传空补全 description明确使用场景工具参数解析失败模型输出非法 JSON查看 trace 里的 raw arguments加 Pydantic 校验并回传错误Agent 陷入死循环无步数上限、工具返回不明确看 trace 里重复的调用序列设 max_steps工具返回加提示长对话后答非所问上下文超限、关键信息被挤出统计每轮 Token 数摘要压缩加结构化状态同一问题结果不稳定温度过高、工具结果非确定性同输入跑十次对比降温度工具结果排序去重接口 504 超时步数过多、单步工具慢看每步 latency 分布拆分任务加单步超时并发上来就崩显存不足、无并发限制看显存曲线和 429 比例加信号量超限返回排队批量任务卡住不动队列阻塞、异常未捕获查任务状态表和日志加任务级超时和失败重试输出内容敏感或越权无内容校验、权限过宽审计工具权限和输出最小权限加人工确认环节评测通过率波动大任务集小、判分器不稳重复跑同一版本对比扩任务集固化判分标准几点补充经验。依赖安装失败大多不是代码问题而是 Python 版本和 wheel 不匹配尤其是涉及编译扩展的包优先用预编译版本或者换 Python 3.10。模型服务连不上时先用一条最简单的 curl 测通别在 Agent 代码里猜网络层和业务层的问题要分开定位。显存不足的表现通常是服务启动就退出或者推理中途 OOM这时候降上下文长度比降精度更有效因为显存占用跟序列长度是平方关系。还有一个经常被忽略的问题进程残留。反复重启服务之后端口被占、显存没释放、GPU 上还挂着僵尸进程表现就是“明明代码没改突然跑不动了”。养成习惯重启前先查端口占用和 GPU 进程确认干净再起。这类环境问题排查起来最费时间但预防成本极低。10. 学习路线与最佳实践把这条路线压缩成可执行的顺序。第一周不碰任何框架纯手写 Agent Loop把工具调用、错误回传、步数上限、日志落盘四件事做扎实跑通三到五个真实任务。第二周加记忆和规划做上下文压缩试一次任务分解对比分解前后的成功率。第三周搭 Harness凑五十条任务集把规则判分跑起来形成第一份基线报告。第四周做服务化和批量测并发、测超时、测成本把指标接上监控。四周下来你手里会有一个能演示、能对比、能讲清楚取舍的项目这比刷完十套教程有用得多。工程实践上有几条值得写进习惯里。一是永远先小参数验证新功能先用两三步、短输入跑通再放开长任务。二是保留一套最小可运行配置模型、超时、工具开关都记在配置里出问题时能快速回退到已知可用状态。三是输入、输出、日志分目录管理按run_id归档出问题能精确定位到某一次运行。四是批量任务必须带幂等键重试不会产生重复副作用。五是接口服务要限制访问范围加认证和限流别把带工具权限的 Agent 裸露在公网上。最后落在合规上。Agent 的能力越强责任边界越要清楚能读文件的要限定目录能执行命令的要放进沙箱能发请求的要走白名单能生成内容的要有审核。涉及他人肖像、声音、作品的素材必须拿到明确授权再处理涉及个人信息的场景日志脱敏、最小化采集、明确留存期限。这些不是给流程加负担而是让系统能长期跑下去的前提。如果只能先做一件事建议从手写那个循环开始加上完整的轨迹日志。有了轨迹你就有了复盘和评测的基础后面所有优化才有对比的基准没有轨迹再多的调参都只是碰运气。把这一层打牢再去看各种编排框架和深度任务方案你会发现它们解决的其实都是你已经遇到过的问题。