> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 每次调用后都创建 PR

export const UseCaseHero = ({title, description, prompt, category, features, devinUrl, agent, intent, playbookId, type}) => {
  const encodedPrompt = encodeURIComponent(prompt || '');
  const tag = 'docs-use-case-gallery';
  const utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=hero-cta';
  const agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  const devinHref = type === 'schedule' ? 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + (prompt ? '&prompt=' + encodedPrompt : '') : type === 'review' ? 'https://app.devin.ai/review?' + utm : agent === 'ada' ? 'https://app.devin.ai/search?' + utm + '&noSubmit=true' + (prompt ? '&prompt=' + encodedPrompt : '') : devinUrl ? devinUrl.includes('?') ? devinUrl + '&' + utm + agentParams : devinUrl + '?' + utm + agentParams : prompt ? 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encodedPrompt : 'https://app.devin.ai/?' + utm + agentParams;
  const buttonLabel = type === 'schedule' ? 'Schedule in Devin ↗' : type === 'review' ? 'Set Up Devin Review ↗' : agent === 'advanced' ? 'Try in Devin ↗' : agent === 'dana' ? 'Try in Dana ↗' : agent === 'ada' ? 'Try in Ask Devin ↗' : 'Try in Devin ↗';
  const featureList = features ? features.split(',').map(f => f.trim()) : [];
  return <div className="uc-hero">
      <div className="uc-hero-inner">
        <div className="uc-hero-left">
          <h1 className="uc-hero-title">{title}</h1>
          <p className="uc-hero-desc">{description}</p>
          <div>
            <a href={devinHref} target="_blank" rel="noopener noreferrer" className="try-in-devin-btn">
              {buttonLabel}
            </a>
          </div>
        </div>
        <div className="uc-hero-meta">
          <div className="uc-meta-item">
            <span className="uc-meta-label">Author</span>
            <span className="uc-meta-value">Cognition</span>
          </div>
          <div className="uc-meta-item">
            <span className="uc-meta-label">Category</span>
            <span className="uc-meta-value">{category}</span>
          </div>
          {featureList.length > 0 && <div className="uc-meta-item">
              <span className="uc-meta-label">Features</span>
              <span className="uc-meta-value">{featureList.join(', ')}</span>
            </div>}
        </div>
      </div>
    </div>;
};

export const PromptBlock = ({children, type, agent, intent, playbookId}) => {
  var utm = 'utm_source=docs&utm_medium=use-case-gallery&utm_campaign=prompt-block';
  var tag = 'docs-use-case-gallery';
  var agentParams = (agent ? '&agent=' + agent : '') + (intent ? '&intent=' + intent : '') + (playbookId ? '&playbookId=' + playbookId : '');
  var label = type === 'schedule' ? 'Schedule in Devin' : type === 'playbook' ? 'Create Playbook' : type === 'knowledge' ? 'Add to Knowledge' : agent === 'advanced' ? 'Try in Devin' : agent === 'dana' ? 'Try in Dana' : agent === 'ada' ? 'Try in Ask Devin' : 'Try in Devin';
  var buildUrl = function (text) {
    var encoded = encodeURIComponent(text);
    if (type === 'schedule') return 'https://app.devin.ai/settings/schedules/create?' + utm + agentParams + '&prompt=' + encoded;
    if (type === 'playbook') return 'https://app.devin.ai/settings/playbooks/create?' + utm + '&body=' + encoded;
    if (type === 'knowledge') return 'https://app.devin.ai/knowledge?' + utm + '&body=' + encoded;
    if (agent === 'ada') return 'https://app.devin.ai/search?' + utm + '&noSubmit=true&prompt=' + encoded;
    return 'https://app.devin.ai/?tags=' + tag + '&' + utm + agentParams + '&prompt=' + encoded;
  };
  const ref = React.useRef(null);
  const [href, setHref] = React.useState('#');
  React.useEffect(() => {
    if (!ref.current) return;
    var codeEl = ref.current.querySelector('pre code');
    if (codeEl) {
      var text = codeEl.textContent.trim();
      if (text) setHref(buildUrl(text));
    }
    var header = ref.current.querySelector('[data-component-part="code-block-header"]');
    if (header && !header.querySelector('.prompt-block-devin-link')) {
      var link = document.createElement('a');
      link.href = href;
      link.target = '_blank';
      link.rel = 'noopener noreferrer';
      link.className = 'prompt-block-devin-link';
      link.style.cssText = 'display:inline-flex;align-items:center;gap:6px;text-decoration:none;color:#fff;font-size:11px;font-weight:500;padding:4px 10px;border-radius:6px;white-space:nowrap;background:#317CFF;transition:background 0.2s;margin-left:8px;';
      link.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg> ' + label;
      link.onmouseenter = function () {
        link.style.background = '#2968D9';
      };
      link.onmouseleave = function () {
        link.style.background = '#317CFF';
      };
      header.appendChild(link);
    }
    var existingLink = ref.current.querySelector('.prompt-block-devin-link');
    if (existingLink && href !== '#') existingLink.href = href;
  });
  return <div className="prompt-block" ref={ref}>{children}</div>;
};

<UseCaseHero title="每次通话后都创建 PR" description="一个每小时运行一次的 Devin 计划会轮询 Granola 中的新会议，从转录内容中提取工程任务，并启动子 Devin 会话来发起 PR。" prompt="设置一个每小时运行一次的 Devin 计划，通过 Granola MCP 服务器轮询 Granola 中的新会议。对于每个转录已准备就绪的会议，提取工程任务并启动子 Devin 会话来发起 PR。使用 Knowledge note 记录已处理的会议。" category="自动化" features="计划, MCP, playbooks, Advanced" type="schedule" agent="devin" />

<div className="uc-detail-wrapper">
  <Tip>不想手动配置？将本页链接粘贴到 Devin session 中，让它帮你完成所有设置。</Tip>

  Granola 可以录制你的会议，并将其转化为笔记、摘要和文字记录。连接 Granola MCP 后，Devin 就能像团队成员一样使用这些会议产出物：了解会议讨论内容、找出具体的工程跟进事项并着手执行。

  将此设置为每小时计划运行，任务即可在你结束通话后立即启动。整个循环在你的 Devin 实例内运行，使用计划、Granola MCP、Knowledge 和子会话。

  ```
  Devin 计划会话（每小时）
    → 通过 MCP 列出最近的 Granola 会议
    → 对于每个新会议（从旧到新）：
        → 获取元数据、笔记、AI 摘要、会议记录
        → 从讨论中识别工程任务
        → 为具体任务启动 Devin 子会话
        → 在 Knowledge 中记录已处理的会议
  ```

  <Steps>
    <Step title="连接 Granola MCP">
      Devin 需要访问你的 Granola 会议，以读取转录内容和笔记。

      1. 前往 **Settings > Connections > MCP servers**，搜索 **Granola**
      2. 点击 **Enable** 并完成身份验证——这将授予 Devin 对你的会议、转录内容和笔记的读取权限
      3. 点击 **Test listing tools**，验证连接是否正常

      连接后，Devin 可以在会话期间调用 `list_meetings`、`get_meetings` 和 `get_meeting_transcript` 来获取会议数据。详细了解如何[配置 MCP 服务器](/zh/work-with-devin/mcp)。
    </Step>

    <Step title="创建一个 processed-meetings 的 Knowledge 笔记">
      Devin 使用一则 [Knowledge](/zh/product-guides/knowledge) 笔记来记录哪些会议已经处理过。这样可以防止在每小时运行时重复处理。

      前往 **设置 > Knowledge**，新建一则笔记：

      * **名称**: `Granola Post-call Processor Meeting Log`
      * **触发条件**: `在运行 Granola 通话后处理器计划会话时，使用此笔记跟踪已处理的会议。`
      * **正文**:

      ```json Granola Post-call Processor Meeting Log theme={null}
      {
        "last_processed_meeting_id": null,
        "last_processed_meeting_time": null,
        "last_processed_title": null,
        "updated_at": null
      }
      ```

      计划会话会将每个成功处理的会议记录在此备注中，这样下次运行时就会从上次结束的地方继续。
    </Step>

    <Step title="撰写 Post-call Operator playbook">
      创建一个[playbook](/zh/product-guides/creating-playbooks)，告诉 Devin 如何处理每场会议。前往 [**Settings > Playbooks**](https://app.devin.ai/settings/playbooks/create?utm_source=docs\&utm_medium=use-case-gallery) 并创建一个新的 playbook：

      <PromptBlock type="playbook">
        ```txt 通话后处理员 theme={null}
        将已结束的 Granola 会议转化为具体的工程工作。
        阅读会议记录，找出每一项可执行的代码任务，并启动
        Devin 子会话来编写 PR。尽可能偏向行动——
        只要某项内容可以变成 PR，就启动它。

        对于每场会议：
        1. 阅读会议记录、AI 摘要以及所有私密笔记
        2. 识别提到或隐含的每一项工程任务：
           - 讨论过的 bug 修复
           - 细节足够明确、可以写出规格的功能请求
           - 已达成一致的重构或改进
           - 研究/调查任务
           - 文档更新
           - 基础架构或 DevOps 变更
        3. 为每项任务写出明确的规格说明：
           - 需要在哪些 repo 中开展工作
           - 这项变更应实现什么
           - 验收标准
           - 会议中的关键背景信息（少量引用即可）
        4. 为每项足够明确、能够
           产出 PR 的任务启动一个 Devin 子会话。将完整规格作为提示提供。
        5. 对于过于模糊、无法形成 PR 的任务，将其列为建议事项，
           并注明缺失的背景信息。
        6. 返回已启动会话和
           建议事项的结构化摘要。

        不要为模糊的想法启动会话。如果某项任务需要
        澄清，请改为将其列为建议事项。
        ```
      </PromptBlock>

      保存后记下 playbook ID——你需要在计划提示中引用它。
    </Step>

    <Step title="创建按小时计划">
      前往 [**设置 > 计划**](/zh/product-guides/scheduled-sessions)，然后点击 **创建计划**。

      * **名称**: `Granola post-call processor`
      * **频率**: 每小时 (`0 * * * *`)
      * **Agent**: Devin — 这会让 Devin 为每个任务启动子会话，从而并行运行修复
      * **Slack channel** (可选) : 选择一个频道，这样当会议处理完成并创建 PR 时，你的团队就会收到通知
      * **提示**:

      <PromptBlock type="schedule" agent="devin">
        ```txt Granola post-call processor theme={null}
        运行 Granola 会后处理器。

        使用 Granola MCP 服务器，以及名为
        "Granola Post-call Processor Meeting Log" 的 Knowledge 笔记。

        1. 检查会议日志，找到上次处理的会议 ID/时间。
        2. 列出过去 24 小时内的 Granola 会议。
        3. 选择比日志中最新会议更新的会议，并按从旧到新的顺序排序。
        4. 对于每场会议：
           a. 通过 MCP 获取元数据、私有笔记和 AI 摘要
           b. 通过 MCP 获取完整转录
           c. 如果转录不可用，则在此处停止处理这一批次
              ——不要跳过继续处理。下次运行时会重试。
           d. 针对这场会议运行 Post-call Operator playbook
           e. 为具体的工程任务启动 Devin 子会话
           f. 在 Knowledge 笔记中记录这场已处理的会议
        5. 在 Slack 中发布摘要：已处理的会议、已启动的会话，
           以及因缺少转录而跳过的会议。

        如果自日志中最新会议以来没有新会议，则安静退出。
        ```
      </PromptBlock>

      如果你想完全自主运行，请将 **bypass approval** 设为 `true`——这样 MCP 工具、Knowledge 更新或创建子会话都无需手动审批。
    </Step>

    <Step title="一次典型运行会生成什么">
      每小时，Devin 都会处理所有新会议，并发起有针对性的 PR。以下是一次真实 session 输出的示例：

      ```
      自最新会议日志条目以来，已处理 1 个新的 Granola 会议：

      会议："Backend API planning"（2026-04-29 下午 2:00）

      已启动的子会话（3 个）：
      1. 修复 /api/invoices 端点中的 N+1 查询
         Repo: acme/api-server
         PR: Eager-load invoice line items to fix timeout
         Session: https://app.devin.ai/sessions/abc123

      2. 为 webhook 端点添加速率限制
         Repo: acme/api-server
         PR: Per-key rate limits on /webhooks/*
         Session: https://app.devin.ai/sessions/def456

      3. 更新新 Billing 端点的 API 文档
         Repo: acme/docs
         PR: Add billing endpoint reference docs
         Session: https://app.devin.ai/sessions/ghi789

      建议操作（1 项）：
      - 排查身份验证令牌刷新流程——被提及为"有时不稳定"，但未指明具体错误或 repo。需要团队提供更多背景信息。

      Knowledge 会议日志已更新至"Backend API planning"（2026-04-29）。
      ```

      每个子会话都会独立运行，并各自创建一个拉取请求 (PR) ，在描述中写入会议背景。
    </Step>

    <Step title="调优和迭代">
      经过几天运行后，回顾哪些做法有效，并进行调整：

      **处理转录延迟。** 当计划处理到某场会议、但其转录尚未准备好时，就会停止处理——这样可以避免因转录延迟而跳过会议。如果你发现转录一直较慢，可以拉长计划间隔，或在提示中加入延迟缓冲。

      **按会议类型限定作用域。** 并不是每场会议都会产出工程工作。可在提示中添加筛选条件，跳过某些类型的会议：

      <PromptBlock agent="advanced">
        ```txt 按类型筛选会议 theme={null}
        更新计划提示：跳过标题中包含
        "1:1"、"standup" 或 "social" 的会议。只处理
        可能包含工程讨论的会议——规划会议、
        bug 分流、设计评审和客户电话。
        ```
      </PromptBlock>

      **从结果中学习。** 几周后，让 Devin 分析哪些子会话产出了已合并的 PR，哪些在未合并时就被关闭。利用这些反馈来完善 playbook 的任务提取标准：

      <PromptBlock agent="advanced">
        ```txt 分析通话后结果并更新 playbook theme={null}
        查看过去 2 周内由 Granola 通话后
        处理器启动的所有子会话。对于每个会话，检查
        PR 是已合并还是已关闭。

        识别其中的模式——哪些任务类型持续产出
        可合并的 PR，哪些过于模糊，以及 playbook
        在哪些地方需要更多上下文。然后根据这些经验，
        为 Post-call Operator playbook 提出更新建议。
        ```
      </PromptBlock>
    </Step>
  </Steps>
</div>
