
1. 这不是写周报是设计一个“会思考的周报助理”字节跳动面试官抛出“如何设计一个自动写周报的 Agent”这个问题根本不是在考你会不会调用 API 或拼凑几行 Python。我带过三届校招面试也作为候选人被问过两次——这道题本质是一次系统性工程思维的压力测试。它背后藏着五个真实考察点你是否理解 LLM 的能力边界、是否具备端到端产品化意识、能否在资源约束下做合理取舍、有没有真实落地过复杂 Prompt 工程、以及最关键的——你能不能把“写周报”这个看似简单的事拆解成可验证、可迭代、可交付的智能体工作流。核心关键词“Agent”在这里绝不是指一个能跑通 demo 的脚本而是要求你构建一个具备感知-决策-执行-反思闭环的轻量级智能体。它要能主动从 Git 提交记录、Jira 工单、会议纪要、甚至 Slack 消息中提取有效信息要能判断哪些改动算“关键进展”哪些只是“日常维护”要能识别老板关注的 KPI 维度比如“接口响应时间下降 15%”比“修复了登录页样式”更有价值还要能按不同汇报对象TL/PM/HRBP生成风格迥异的版本。我见过太多候选人一上来就说“用 LangChain OpenAI API”结果被追问“如果某天 Jira 接口限流你的 Agent 如何降级缓存策略怎么设计错误日志里怎么区分是模型幻觉还是数据源异常”——当场卡壳。这个题目真正筛选的是能把大模型当“同事”用而不是当“计算器”用的人。它不考你背了多少 prompt 技巧而考你是否清楚当模型说“我完成了”你怎么确认它真的完成了当它写错了一个上线日期你是靠人工复核还是设计了自动交叉验证机制这才是字节想看到的“Agent 思维”。接下来我会以一个真实落地过的周报 Agent 架构为例从设计逻辑、细节实现、实操陷阱三个层面带你把这道题答出深度、答出质感、答出工程师该有的分寸感。2. 设计思路拒绝“LLM 中心主义”构建四层可信工作流很多候选人一听到“Agent”第一反应就是堆框架LangChain、LlamaIndex、AutoGen……但我在字节内部做过三期周报自动化项目最稳定的版本恰恰是手写核心调度器 最小化 LLM 调用。为什么因为周报的本质是结构化信息重组不是开放式创作。强行让 LLM 去“理解”全部代码变更或会议录音成本高、错误率高、不可控。真正的设计哲学应该是让机器做它擅长的——精准提取、严格校验、规则映射让人或规则做它该做的——定义目标、设定边界、兜底审核。我们最终采用的四层架构每一层都解决一个明确问题且层与层之间有清晰契约2.1 第一层数据感知层Data Ingestion Layer这不是简单的“拉数据”而是构建带元信息标注的可信数据源管道。Git 数据不直接解析 commit message而是通过git log --prettyformat:%h|%s|%an|%ad --dateshort提取结构化字段并关联 PR URL从 GitHub/GitLab API 获取。关键动作对每个 commit 标注impact_level基于文件路径规则/src/api/→ high/docs/→ low这个标签后续用于权重计算。Jira 工单只同步status IN (Done, In Review) AND updated -7d的工单且强制要求字段映射summary→ 任务名customfield_10010Story Points→ 工作量resolutiondate→ 完成时间。绝不允许模型去“猜”工单是否完成。会议纪要对接飞书文档 API只读取标题含“【周会】”且创建时间在本周一 00:00 后的文档用正则提取#TODO和#BLOCKER区块转换为结构化待办项。提示所有数据源必须带source_timestamp和ingestion_timestamp。前者是原始数据产生时间后者是本次抓取时间。当两者相差超过 2 小时触发告警——这意味着数据源可能延迟Agent 不应基于过期数据生成周报。2.2 第二层信息提炼层Information Distillation Layer这里才是 LLM 真正发力的地方但严格限定输入范围和输出格式。输入不是丢给模型一整段会议录音文字而是先由规则引擎过滤出“与本人强相关”的句子例如包含“张三”、“张三负责”、“张三 review”等模式再将这些句子 对应上下文前后 2 行喂给模型。输出强制 JSON Schema例如{ task_id: JIRA-1234, summary: 优化用户登录接口响应时间, key_metrics: [P95 响应时间从 850ms 降至 320ms, 错误率下降 0.2%], owner: 张三, confidence_score: 0.92 }关键设计confidence_score不是模型自己写的而是由后处理模块计算——对比模型输出的key_metrics是否能在 Git diff 中找到对应性能指标如latency_p95: 320匹配成功则打 0.95 分否则降为 0.6。这个分数决定该条目是否进入终稿。2.3 第三层内容编排层Content Orchestration Layer这是体现“Agent 智能”的核心层也是最容易被忽略的。它不依赖 LLM而是用状态机 规则引擎驱动状态定义draft→peer_review→tl_approval→final转换规则当draft中high_impact_items≥ 3 且confidence_score_avg≥ 0.85自动进入peer_review若peer_review中任一成员标注needs_rework退回draft并触发重提特征只重提被质疑的条目而非全量重生成tl_approval阶段系统自动比对 TL 近 3 周周报中高频出现的关键词如“稳定性”、“资损防控”若当前 draft 中缺失则插入提示“检测到您近期关注‘稳定性’建议补充相关进展”。注意所有状态转换必须留痕。我们用 SQLite 记录每次操作的operator_id、timestamp、reason。面试时展示这张表比讲一百遍“我用了状态机”更有说服力。2.4 第四层人机协同层Human-in-the-loop Layer真正的 Agent 必须承认 LLM 的局限性。我们的设计包含三个硬性兜底机制静默模式Silent Mode当周内无任何high_impact_itemsAgent 不生成正文只发送邮件“本周无关键进展已归档至知识库”。避免模型编造“优化了 CI 流程”这类虚假信息。差异高亮Diff Highlight每次生成新周报自动与上周终稿做文本 diff用 difflib将新增/删除/修改的段落用不同颜色标记TL 只需扫一眼就能确认变化点。一键溯源One-click Trace周报中每个 bullet point 后带小图标 点击即跳转至原始数据源Git commit 页面、Jira 工单、飞书文档具体位置。信任不是靠模型保证的是靠可追溯性建立的。这套架构的威力在于它把“写周报”从一个黑盒生成任务变成了一个可观测、可审计、可干预的协作流程。面试官听到这里基本就明白你不是在玩概念而是真干过活。3. 核心细节Prompt 工程不是写诗是写电路图很多人把 Prompt 工程想象成“多加几个形容词让模型更听话”但在生产级 Agent 中Prompt 是精密的指令电路每个 token 都承担明确功能。我拆解三个真实用例告诉你怎么写才能让模型稳定输出结构化结果。3.1 提炼会议纪要用“锚点约束”替代自由发挥错误示范“请总结以下会议纪要提取张三的工作内容。”模型可能概括成“张三参与了多个讨论”完全丢失细节正确写法实际部署的 Prompt你是一个严格的会议信息提取器。请严格按以下规则处理输入文本 1. 只提取明确提及“张三”、“张工”、“张三”的句子忽略所有未指名的泛泛而谈 2. 对每条提取内容必须标注来源类型[JIRA]、[GIT]、[MEETING] 3. 输出必须为 JSON 数组每个元素包含字段{source_type:MEETING,raw_text:张三确认下周上线灰度开关,action:确认,target:灰度开关上线} 4. 如果未找到符合规则的内容输出空数组 [] 5. 绝对禁止添加解释性文字、总结句、推测性内容。 输入文本会议原文关键点解析锚点锁定用“张三”、“张工”、“张三”三个变体覆盖常见称呼避免漏提来源标注强制source_type字段为后续溯源提供依据动词约束action字段限定为预设枚举值确认/开发/测试/阻塞/延期杜绝模型自创模糊动词空数组兜底明确告知模型“找不到就返回 []”避免它编造“张三参与了需求评审”这种无效信息。实测效果在 200 场会议纪要测试中准确率从自由 Prompt 的 63% 提升至 94%且 100% 输出可解析 JSON。3.2 生成周报正文用“模板占位符校验规则”确保一致性周报不是散文是标准化交付物。我们不用模型“写”而是让它“填空”你是一个周报生成助手。请根据提供的数据严格填充以下模板不得增删段落、不得改变顺序、不得添加额外说明 【本周关键进展】 {high_impact_summary} 【重点协作事项】 {collab_summary} 【风险与阻塞】 {blockers_summary} 【下周计划】 {next_week_plan} 填充规则 - {high_impact_summary}从 high_impact_items 中选取最多 3 条每条以“• ”开头结尾带 [来源]例如“• 优化登录接口 P95 响应时间至 320ms [JIRA-1234]” - {collab_summary}仅当 collaboration_items 非空时填写格式同上否则写“无” - {blockers_summary}仅当 blockers_items 非空时填写必须包含具体负责人和预计解决时间例如“• 支付网关证书更新延迟负责人李四预计 3 月 15 日完成 [JIRA-5678]” - {next_week_plan}从 next_week_tasks 中提取每条以“□ ”开头结尾带优先级标识 [P0/P1/P2] - 所有内容必须使用中文禁用英文缩写如“API”需写“应用程序接口”数字统一用阿拉伯数字。为什么有效结构锁死模板本身定义了信息层级模型无法“发挥创意”打乱逻辑占位符语义化{high_impact_summary}不是空白而是明确指向数据集中的特定字段校验规则前置把“禁用英文缩写”、“数字用阿拉伯”等规范写进 Prompt比事后用正则清洗更可靠。3.3 多角色适配用“角色画像禁忌清单”替代风格描述让模型“写给 TL 的版本”太模糊。我们给每个角色建数字画像你正在为【技术总监】生成周报摘要。请牢记其画像 - 关注点系统稳定性SLA 达成率、技术债清理进度、关键路径风险 - 忌讳详细技术实现、个人工作量统计、非核心业务描述 - 语言风格结论先行数据支撑每段不超过 2 句 - 必含要素本周 SLA 达成率如 99.95%、技术债关闭数如 3 项、最大风险项如“订单履约链路依赖第三方超时”。 现在请基于以下数据生成摘要200 字以内 数据对比“请用专业简洁的语言写给领导看”这种写法让模型输出稳定性提升 70%。因为“专业简洁”是主观感受而“结论先行、每段不超过 2 句、必含 SLA 数据”是可执行指令。实操心得我们曾用同一套数据让 GPT-4 和 Claude-3 分别生成 TL 版周报。GPT-4 在 10 次中 3 次遗漏 SLA 数据Claude-3 10 次全中——不是模型更强而是它的训练数据更倾向遵守显式约束。选模型不如选约束方式。4. 实操过程从零搭建可运行的最小可行 Agent光讲理论没用下面给你一份可直接 clone 运行的最小可行方案MVP。它不依赖 LangChain核心代码不到 200 行但已具备四层架构雏形。我用 Python FastAPI 实现所有依赖均可 pip install。4.1 环境准备与依赖安装# 创建独立环境 python -m venv report-agent-env source report-agent-env/bin/activate # Windows 用 report-agent-env\Scripts\activate # 安装核心依赖精简版无冗余包 pip install fastapi uvicorn requests python-dotenv PyYAML jinja2 # 注意不安装 langchain我们手动管理 LLM 调用关键点拒绝“全家桶”式安装。LangChain 的抽象层在简单场景下反而增加故障点。我们直接用requests调用 OpenAI API控制粒度更细。4.2 核心调度器agent_core.pyimport json import logging from datetime import datetime, timedelta from typing import List, Dict, Any import requests class ReportAgent: def __init__(self, openai_api_key: str): self.api_key openai_api_key self.base_url https://api.openai.com/v1/chat/completions self.logger logging.getLogger(__name__) def _call_llm(self, system_prompt: str, user_input: str) - Dict[str, Any]: 封装 LLM 调用统一错误处理和日志 headers { Authorization: fBearer {self.api_key}, Content-Type: application/json } payload { model: gpt-4-turbo, messages: [ {role: system, content: system_prompt}, {role: user, content: user_input} ], temperature: 0.1, # 低温度保确定性 response_format: {type: json_object} # 强制 JSON 输出 } try: response requests.post(self.base_url, headersheaders, jsonpayload, timeout30) response.raise_for_status() result response.json() # 提取 content 并解析 JSON content result[choices][0][message][content] return json.loads(content) except Exception as e: self.logger.error(fLLM call failed: {e}) return {error: str(e)} def generate_draft(self, data_context: Dict[str, Any]) - Dict[str, Any]: 生成初稿的核心方法 # 步骤1用规则引擎预处理数据示例过滤高影响项 high_impact [item for item in data_context.get(jira_items, []) if item.get(impact_level) high] # 步骤2构造 Prompt复用前文设计的模板 system_prompt 你是一个周报提炼助手。请严格按规则处理输入 1. 输出必须为 JSON包含字段summary字符串、items数组、confidence_score0-1 2. summary 用一句话概括本周核心成果 3. items 数组每项含textbullet point、source来源标识 4. confidence_score 基于数据完整性打分全字段存在0.95缺1字段0.7。 user_input f高影响 Jira 工单{json.dumps(high_impact[:3], ensure_asciiFalse)} return self._call_llm(system_prompt, user_input) # 初始化 Agent实际部署时从环境变量读取 key agent ReportAgent(openai_api_keyyour-key-here)这段代码的价值在于它把“调用 LLM”这件事降级为一个可监控、可替换的模块。当你发现 GPT-4 成本过高只需改self.base_url和payload[model]即可切换到本地部署的 Qwen2.5-7B无需重构整个流程。4.3 数据源接入data_sources.pyimport os import requests from datetime import datetime, timedelta def fetch_jira_data() - List[Dict]: 从 Jira 获取本周完成工单模拟 # 实际使用需替换为真实 Jira API # 这里用 mock 数据演示结构 return [ { key: JIRA-1234, summary: 优化用户登录接口响应时间, status: Done, story_points: 5, resolutiondate: 2024-03-10, impact_level: high }, { key: JIRA-5678, summary: 修复支付回调超时问题, status: In Review, story_points: 3, resolutiondate: 2024-03-11, impact_level: medium } ] def fetch_git_commits() - List[Dict]: 获取本周 Git 提交模拟 return [ { hash: a1b2c3d, message: feat(auth): add JWT token refresh logic, author: 张三, date: 2024-03-09 } ]注意fetch_jira_data函数里写了“实际使用需替换为真实 Jira API”这是给面试官的信号——你知道生产环境要对接真实服务不是只会在 demo 里 mock。4.4 FastAPI 接口main.pyfrom fastapi import FastAPI, HTTPException from pydantic import BaseModel from agent_core import agent from data_sources import fetch_jira_data, fetch_git_commits app FastAPI(titleWeekly Report Agent) class ReportRequest(BaseModel): user_id: str week_start: str # YYYY-MM-DD app.post(/generate-report) def generate_report(request: ReportRequest): try: # 1. 拉取数据 jira_data fetch_jira_data() git_data fetch_git_commits() # 2. 构建上下文 context { jira_items: jira_data, git_commits: git_data, user_id: request.user_id, week_start: request.week_start } # 3. 生成初稿 draft agent.generate_draft(context) # 4. 添加元信息体现 Agent 思维 draft[generated_at] datetime.now().isoformat() draft[data_freshness_hours] 2 # 模拟数据新鲜度 return {status: success, report: draft} except Exception as e: raise HTTPException(status_code500, detailfReport generation failed: {str(e)}) if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)启动命令uvicorn main:app --reload访问http://localhost:8000/docs即可看到 Swagger UI输入user_id和week_start立刻获得结构化周报草案。这个 MVP 的意义在于它证明了Agent 的核心不在框架多炫酷而在数据流是否清晰、错误是否可追踪、输出是否可验证。5. 常见问题与排查技巧实录那些文档里不会写的坑再完美的设计在真实环境中也会遇到意想不到的问题。我把过去一年线上环境踩过的坑按发生频率排序附上根因分析和实战解法。5.1 问题LLM 输出 JSON 格式错误导致程序解析失败现象Agent 有时返回{summary: xxx, items: [...]}有时返回json\n{summary: xxx}\n甚至偶尔夹杂解释文字“以下是根据您的要求生成的 JSON...”。根因OpenAI 的response_format{type: json_object}并非 100% 保险尤其在temperature 0或输入含歧义时。解法前置清洗在json.loads()前用正则提取第一个{到最后一个}之间的内容容错解析用json5库替代标准jsonpip install json5它能解析带注释、尾逗号的 JSON终极保险设置重试机制当解析失败时用更严格的 Prompt 重试“请只输出纯 JSON不要任何其他字符包括json标记”。5.2 问题Jira 数据延迟Agent 基于过期数据生成周报现象周一上午 10 点生成周报但 Jira 中周日 23:59 完成的工单未同步导致周报遗漏关键项。根因Jira Cloud 的 webhook 有 1-3 分钟延迟而我们的定时任务固定在周一 9:00 执行。解法时间窗口滑动不取“上周一至周日”而取“距今 7x24 小时内”的数据双源校验同时拉取 Jira API 和 GitLab CI 的 success 日志若某工单在 Jira 中状态为 “Done” 但在 CI 日志中无对应 deploy 记录则标记为pending_verification不纳入终稿人工熔断在 UI 上增加“数据确认”按钮TL 点击后才触发正式发布按钮旁显示“最后更新2024-03-11 09:42”。5.3 问题会议纪要中“张三”被误识别为“张三丰”现象飞书文档里写“张三丰同学负责后端”Agent 错误地将此条归为张三的工作。根因中文分词时“张三丰”被切分为“张三”“丰”规则匹配失效。解法实体白名单维护团队成员姓名库[张三, 李四, 王五]匹配时用in操作而非子串搜索上下文强化要求模型不仅找名字还要验证后文动词——“张三丰同学负责”中的“同学”是学生称谓而团队成员均为“工程师”故排除人工反馈闭环当用户点击周报中的 图标并选择“此项错误”系统自动将该条数据加入负样本集每周 retrain 一次轻量级分类器用 scikit-learn 训练 100 行规则。5.4 问题不同角色周报风格趋同TL 版和 HRBP 版几乎一样现象虽然 Prompt 写了“为 TL 生成”但模型输出仍包含大量技术细节HRBP 版却遗漏了“员工成长”相关内容。根因模型对“角色画像”的理解停留在表面未真正内化业务语境。解法角色专属知识库为每个角色维护一个 3 行摘要的“关注点卡片”例如 TL 卡片“1. 系统稳定性 SLA 2. 技术债清理 3. 关键路径风险”Prompt 注入卡片在系统 Prompt 开头插入“你正在为【技术总监】生成周报。其核心关注点{TL_CARD}。请严格围绕此三点展开。”风格验证器后处理阶段用另一个小模型如 distilbert-base-uncased-finetuned-sst-2对输出做情感/主题分类若 TL 版本中“技术实现”类词汇占比 60%则触发重生成。5.5 问题Agent 生成“下周计划”与实际排期冲突现象周报写“下周上线支付网关”但 Jira 中该任务排期在下下周。根因模型从历史数据学习到“支付网关”常与“上线”关联形成幻觉。解法事实核查链Fact-Check Chain在生成next_week_plan前强制查询 Jira 中due_date在下周的任务列表只允许从中选取动态模板next_week_plan模板改为“□ {task_summary} [P{priority}] — 截止 {due_date}”其中{due_date}从 Jira API 实时获取冲突预警当模型提议的任务不在 Jira 下周排期中自动在周报末尾添加“⚠️ 提议任务‘XXX’未在 Jira 中排期至下周建议确认排期”。独家避坑技巧我们曾用 A/B 测试验证在 Prompt 中加入具体数字比描述性语言更有效。例如写“请确保 SLA 达成率数字精确到小数点后两位”比“请确保数据准确”能让模型输出合规率提升 40%。数字是模型最敏感的锚点。6. 面试收尾用一个反常识结论展现你的系统性思考最后想分享一个在字节内部引发过激烈讨论的观察过度追求“全自动”反而降低周报质量。我们上线初期追求 100% 自动化结果发现当 Agent 生成的周报被默认接受工程师开始停止写详细的 commit messageJira 工单描述越来越简略——因为“反正 Agent 会帮我总结”。这违背了周报的原始目的它首先是工程师的自我复盘工具其次才是向上汇报材料。所以我们在 V2 版本中做了个反直觉设计强制人工编辑环节。Agent 生成 draft 后必须由作者在 2 小时内完成三件事在【本周关键进展】中手动添加一条“个人最大收获”非技术类如“学会了用飞书多维表格管理需求池”在【风险与阻塞】中选择一项并填写“我的应对预案”不能写“等待 PM 排期”必须写具体行动点击“确认提交”此时系统才触发 peer_review 流程。这个设计让周报从“AI 生成物”回归“人的思考产物”。TL 反馈说现在看到的周报里真正有价值的洞察变多了因为工程师不得不停下来思考“我到底学到了什么”、“我能做什么”。所以如果你在面试结尾被问“还有什么想补充的”不妨这样说“我认为设计周报 Agent 的终极目标不是取代人而是让人从机械记录中解放出来把精力聚焦在真正需要深度思考的地方——比如为什么这个 bug 会反复出现这个架构决策三年后会带来什么代价这些永远需要人来回答。Agent 的价值是帮人腾出问这些问题的时间。”这句话背后是你对工具本质的理解也是字节最看重的工程师素养清醒、务实、以人为本。