跳到主内容
快讯直播
AI智模界
教程

Claude Meetings 实战:会议讨论转任务清单

这篇能做出什么

一场 45 分钟的产品周会结束后,能在几分钟内拿到这样一份结构化清单,并直接写进项目管理工具:

```json

[

{

"title": "补齐注册页的错误提示文案",

"owner": "李敏",

"due_date": "2025-04-18",

"priority": "P1",

"acceptance_criteria": "空手机号、格式错误、已注册三种情况各有独立提示,且通过文案评审",

"evidence": "李敏说这个她本周内补,周五前给到设计和前端",

"status": "confirmed",

"source_quote": "……"

},

{

"title": "确认三方登录是否纳入本次迭代",

"owner": null,

"due_date": null,

"priority": "P2",

"acceptance_criteria": "给出纳入或不纳入的结论与理由",

"evidence": "会上没定下来,说下次再聊",

"status": "tentative",

"source_quote": "……"

}

]

```

关键点在于:有主的任务直接建单,没主的任务进「待确认」区,不硬猜。 这比让模型自由发挥写一段纪要摘要有用得多——纪要没人看,任务会被人追。

整条链路是三段:会议内容接入 → 用固定模板提取 → 幂等同步到项目管理工具。下面按顺序拆开。

前置条件清单

开始前把这些准备好,后面每一步都依赖它们:

1. 一个 Claude 账号,能使用对话界面;如果要批量跑,还需要 API Key(在官方控制台生成,具体入口以官方文档为准)。

2. 会议录制与转写能力。大多数会议平台(Zoom、Teams、飞书会议、腾讯会议等)自带云录制和转写,能导出 VTT / SRT / TXT。没有的话,用手机录音 + 任意转写工具也可以,格式统一成纯文本就行。

3. 参会人名单。这是刚需,后面用来约束任务负责人,防止模型编造人名。

4. 一个项目管理工具和它的 API AI 词典:Token">Token。GitHub Issues、Jira、Linear、飞书多维表格、Notion 数据库都行,本文用 GitHub Issues 做完整示例,其它工具换接口地址和字段名即可。

5. 本地环境:Python 3、requests 库、curl。pip install requests 就够。

6. 一份任务模板。下一步会给,可以直接抄。

关于 Claude 侧的会议接入能力(连接器、会议助手入口、可用的集成列表),不同订阅计划的开放范围不一样,以官方文档当前版本为准。但下面的做法不依赖具体入口——只要能拿到转写文本,流程就能跑通。

第 1 步:把会议内容接进来

路线 A:会议平台导出转写(最稳)

会议结束后在会议平台的录制/转写列表里导出字幕文件。VTT 长这样:

```text

WEBVTT

00:00:12.000 --> 00:00:18.000

李敏: 注册页那个错误提示,我这周内补一下

00:00:18.500 --> 00:00:24.000

王强: 好,那三方登录这次还做吗

```

字幕带时间戳和说话人,信息量比纯文本大,尽量保留。但 VTT 有时间轴、样式标签,直接喂给模型是浪费 token,先清洗。

```python

clean_vtt.py

import re

import sys

def clean_vtt(path: str) -> str:

lines = open(path, encoding="utf-8").read().splitlines()

out, seen = [], set()

for line in lines:

if line.strip() == "WEBVTT" or "-->" in line:

continue

line = re.sub(r"<[^>]+>", "", line).strip() # 去掉样式标签

if not line or line.isdigit(): # 去掉纯序号行

continue

key = line

if key in seen: # 连续重复行去重

continue

seen.add(key)

out.append(line)

同一说话人的连续行合并,减少行数

merged = []

for line in out:

if merged and line.split(":")[0] == merged[-1].split(":")[0] and ":" in line:

merged[-1] += " " + line.split(":", 1)[1].strip()

else:

merged.append(line)

return "\n".join(merged)

if __name__ == "__main__":

print(clean_vtt(sys.argv[1]))

```

```bash

python clean_vtt.py meeting.vtt > meeting.txt

```

路线 B:直接在 Claude 对话里处理

不想写代码,就在对话里贴转写文本 + 模板(第 2 步那个),让它按 JSON 输出。适合单场会议、临时处理。

路线 C:桌面端连接器 / MCP

如果已经在用 Claude 桌面端,可以通过 MCP 把项目管理工具接进来,让它读会议文档、写任务单。配置一般放在 claude_desktop_config.json:

```json

{

"mcpServers": {

"project-tool": {

"command": "npx",

"args": ["-y", "你的-mcp-server-包名"],

"env": {

"BASE_URL": "https://your-project-tool.example.com",

"API_TOKEN": "替换为你的 token"

}

}

}

}

```

包名和参数以所选 MCP server 的官方 README 为准,不要照抄示例里的占位值。

第 2 步:写一个稳定出结构的提取模板

这一步决定成败。模板写不好,模型会给一堆"加强沟通""持续优化"这类没法执行的任务。核心是把规则写死。

系统提示(system)

```text

你是会议纪要转任务的解析器。你的唯一输出是合法 JSON 数组,不要输出解释、不要加代码块标记。

每条任务对象包含字段:

  • title: 动词开头的任务标题,不超过 30 字
  • owner: 负责人姓名,只能取自给定的参会人名单;无法确定时写 null
  • due_date: YYYY-MM-DD;无法确定时写 null
  • due_date_raw: 会上关于时间的原话,没有则写 null
  • priority: P0 / P1 / P2 三选一,按会上明确的紧急程度判断,没有明说就填 P2
  • acceptance_criteria: 怎样算做完,一句话,可验证
  • evidence: 支持这条任务的会议原话摘录,不超过 50 字
  • status: confirmed(有人认领且有明确动作)或 tentative(只是提到、没定人、没定时间)
  • dependencies: 依赖的其他任务标题数组,没有则空数组

硬性规则:

1. 只提取有行动承诺的内容。纯信息同步、纯表态不产出任务。

2. owner 必须来自参会人名单,禁止编造人名。找不到就 null。

3. 一条任务对应一个交付物。会上说"顺便把 A 和 B 也做了",拆成两条。

4. 相对时间要结合会议日期换算成绝对日期。换算不了就 null,并在 due_date_raw 保留原话。

5. 每条任务必须有 evidence,evidence 必须是转写文本里真实出现的原话。

6. 讨论没有结论的话题,输出一条 status 为 tentative 的任务,title 用"确认……"开头。

7. 转写里说话人识别不清时,宁可 owner 写 null,也不要猜。

```

用户消息(user)

```text

会议日期:2025-04-15

会议主题:产品周会

参会人:李敏、王强、张倩、陈昊

以下是转写文本:

<transcript>

{这里放 clean_vtt 的输出}

</transcript>

```

几个规则值得单独说:

  • 必须要求 evidence。有了原文摘录,人工复核时能三秒判断这条任务是不是模型瞎编的。这是整套流程里最值钱的一条约束。
  • 允许输出 null。不给模型"必须填"的压力,它就不会编人名和日期。宁可多一条待确认,不要多十条假任务。
  • 区分 confirmed / tentative。会上一半的讨论是没结论的,硬转成任务会让看板迅速变脏。

第 3 步:跑通一次 API 调用

先用 curl 确认请求能通。准备 payload.json:

```json

{

"model": "替换为官方文档中的当前模型 ID",

"max_tokens": 4000,

"system": "把第 2 步的系统提示粘进来",

"messages": [

{

"role": "user",

"content": "会议日期:2025-04-15\n参会人:李敏、王强、张倩、陈昊\n\n转写文本:\n(此处粘贴)"

}

]

}

```

```bash

curl https://api.anthropic.com/v1/messages \

-H "x-api-key: $ANTHROPIC_API_KEY" \

-H "anthropic-version: 2023-06-01" \

-H "content-type: application/json" \

-d @payload.json

```

模型 ID 不要写死,model 字段填官方文档里当前可用的型号,换模型时只改这一处。

跑通后换成脚本,一次处理整场会议:

```python

extract_tasks.py

import json

import os

import re

import sys

import requests

API_URL = "https://api.anthropic.com/v1/messages"

MODEL = os.environ.get("CLAUDE_MODEL", "替换为当前模型 ID")

API_KEY = os.environ["ANTHROPIC_API_KEY"]

SYSTEM = open("system_prompt.txt", encoding="utf-8").read()

def call_claude(transcript: str, meta: str) -> str:

resp = requests.post(

API_URL,

headers={

"x-api-key": API_KEY,

"anthropic-version": "2023-06-01",

"content-type": "application/json",

},

json={

"model": MODEL,

"max_tokens": 4000,

"system": SYSTEM,

"messages": [{

"role": "user",

"content": f"{meta}\n\n转写文本:\n<transcript>\n{transcript}\n</transcript>"

}],

},

timeout=120,

)

resp.raise_for_status()

return resp.json()["content"][0]["text"]

def parse_json(text: str):

模型偶尔会包一层代码块,兜底剥掉

text = re.sub(r"^``(?:json)?|``$", "", text.strip(), flags=re.MULTILINE).strip()

return json.loads(text)

if __name__ == "__main__":

transcript = open(sys.argv[1], encoding="utf-8").read()

meta = "会议日期:2025-04-15\n参会人:李敏、王强、张倩、陈昊"

tasks = parse_json(call_claude(transcript, meta))

json.dump(tasks, open("tasks.json", "w", encoding="utf-8"),

ensure_ascii=False, indent=2)

print(f"提取到 {len(tasks)} 条任务")

```

长会议会超出上下文窗口。处理办法是按时间分段:每 20 分钟切一段,各跑一次,最后按 title 合并去重。分段的坏处是跨段的依赖关系会丢,可以在合并后再跑一次"补依赖"的轻量调用。

第 4 步:本地校验,人工过一遍

模型输出不能直接进系统。加一层校验脚本,把明显有问题的拦下来:

```python

validate.py

import json, datetime, sys

tasks = json.load(open("tasks.json", encoding="utf-8"))

roster = {"李敏", "王强", "张倩", "陈昊"}

problems = []

for i, t in enumerate(tasks):

if not t.get("title"):

problems.append(f"[{i}] 缺 title")

if t.get("owner") and t["owner"] not in roster:

problems.append(f"[{i}] owner 不在名单:{t['owner']}")

t["owner"], t["status"] = None, "tentative"

d = t.get("due_date")

if d:

try:

datetime.date.fromisoformat(d)

except ValueError:

problems.append(f"[{i}] 日期格式不对:{d}")

t["due_date"] = None

if t.get("status") == "confirmed" and not t.get("owner"):

t["status"] = "tentative"

if not t.get("evidence"):

problems.append(f"[{i}] 缺 evidence,需人工确认")

标题近似去重

seen = {}

for t in tasks:

key = "".join(t["title"].split())[:12]

if key in seen:

problems.append(f"疑似重复:{t['title']} / {seen[key]}")

else:

seen[key] = t["title"]

json.dump(tasks, open("tasks.json", "w", encoding="utf-8"),

ensure_ascii=False, indent=2)

print("\n".join(problems) or "校验通过")

```

校验之后一定要人看一眼,重点看两类:status 为 tentative 的(要不要真的建单),以及 evidence 对不上的(可能是幻觉)。这个动作花两分钟,能省掉后面一周的看板噪音。

第 5 步:同步到项目管理工具

核心是幂等

会议重跑、脚本重试、下周一又跑了一次同一场会——这些都会导致重复建单。解决办法是给每条任务算一个稳定的外部 ID:

```python

import hashlib

def external_id(meeting_id: str, task: dict) -> str:

raw = f"{meeting_id}|{task['title']}|{task.get('owner') or ''}"

return "mtg-" + hashlib.sha1(raw.encode()).hexdigest()[:12]

```

建单前先按这个 ID 搜一遍,存在就跳过或更新,不存在才创建。也可以把它写进任务描述里当标记。

GitHub Issues 完整示例

```python

sync_github.py

import json, os, requests

TOKEN = os.environ["GITHUB_TOKEN"]

REPO = os.environ["GITHUB_REPO"] # 形如 your-org/your-repo

API = f"https://api.github.com/repos/{REPO}/issues"

HEAD = {

"Authorization": f"Bearer {TOKEN}",

"Accept": "application/vnd.github+json",

}

def build_body(t: dict, ext_id: str) -> str:

return (

f"验收标准:{t.get('acceptance_criteria') or '待补充'}\n\n"

f"会议原话:> {t.get('evidence') or ''}\n\n"

f"截止:{t.get('due_date') or '待定'}"

f"(原话:{t.get('due_date_raw') or '无'})\n\n"

f"<!-- {ext_id} -->"

)

def already_exists(ext_id: str) -> bool:

r = requests.get(API, headers=HEAD,

params={"state": "all", "per_page": 100}, timeout=30)

r.raise_for_status()

return any(ext_id in (i.get("body") or "") for i in r.json())

for t in json.load(open("tasks.json", encoding="utf-8")):

if t["status"] != "confirmed":

continue # 待确认的先不建单

ext = external_id("2025-04-15-产品周会", t)

if already_exists(ext):

print("跳过重复:", t["title"])

continue

payload = {

"title": t["title"],

"body": build_body(t, ext),

"labels": [t["priority"], "from-meeting"],

}

r = requests.post(API, headers=HEAD, json=payload, timeout=30)

r.raise_for_status()

print("已创建:", r.json()["html_url"])

```

换成 Jira 就是 POST /rest/api/3/issue,换成飞书多维表格就是写入记录接口——字段映射换一下,幂等逻辑照搬。负责人字段各平台要求不同(有的要用户 ID 而不是姓名),需要先做一次姓名到 ID 的映射表,别把中文名直接塞进 assignee。

待确认任务怎么办

两条路:一是写进一张「待确认」表(多维表格或单独的 Issue 池),下次会议开头花三分钟过一遍;二是直接留在 tasks.json 里,人工筛完再跑一次同步。推荐前者,因为没结论的讨论本身就是需要跟进的信息。

第 6 步:固化成日常流程

跑通一次之后把它变成不用想的动作:

```bash

会议结束后按顺序执行

python clean_vtt.py raw/2025-04-15.vtt > meeting.txt

python extract_tasks.py meeting.txt

python validate.py

python sync_github.py

```

包成脚本或 Makefile,会议结束点一下。想更进一步,用会议平台的录制完成 webhook 触发,或者用 cron 每天固定时间扫一遍当天的转写目录。

常见坑与排错

现象原因处理
任务全是"加强沟通""持续跟进"模板没约束动作和交付物在系统提示里加一句:title 必须以动词开头且能对应一个具体交付物
出现会里没提过的人名模型在补全强制 owner 从名单取,配合第 4 步的名单校验兜底
截止日期全是会议当天相对时间没换算提示里明确给出会议日期,要求先换算再输出
同一场会重复建单缺少幂等键用 title + owner 计算哈希,建单前先搜
长会议解析到一半就断超上下文按时间分段,20 分钟一段,合并后补依赖
说话人识别错乱转写质量差让 owner 允许为 null,宁可待确认;重要会议用带说话人分离的转写
API 报 429并发过高加指数退避重试,批处理串行跑
输出不是合法 JSON模型加了说明文字提示里要求"只输出 JSON",脚本里再做一次代码块剥离兜底

还有一条容易被忽略:会议内容里可能有薪酬、人事、客户隐私信息。把整段转写发给外部接口之前,确认所在公司的数据合规要求;必要时先做脱敏,把具体金额、手机号、身份证号替换掉再发。

下一步建议

跑顺之后,可以往前推三步:

1. 加一块决策记录。同样的模板再输出一个 decisions 数组,记录"决定了什么、为什么、谁反对"。任务会过期,决策不会,日后回查价值更高。

2. 做闭环回写。每天把任务完成情况拉一遍,下次开会前自动生成"上次会后的任务进展"放进会议材料开头。这一步做完,会议本身会变短。

3. 让 Claude 直接读写工具。通过 MCP 把项目管理工具接进对话,会上一边讨论一边建单,会后不用再跑同步脚本。这条路对配置要求高一些,但省掉的是最枯燥的那一段。

先用一场真实的会跑一遍,把 tasks.json 导出来和人工整理的清单对一遍。差在哪里,就回去改模板里的那一条规则——模板是这套流程里唯一需要反复打磨的东西。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。