標籤: Claude Managed Agents

  • Claude 私有化:自托管沙箱與 MCP 隧道實戰

    Claude 私有化:自托管沙箱與 MCP 隧道實戰

    📌 本文重點

    • 模型與編排托管在 Anthropic,工具與資料留在你 VPC
    • 透過 self‑hosted sandbox 把程式執行權收回內網
    • 用 MCP tunnel 只開安全出站連線打通內網工具
    • 權限設計與審計要靠嚴格的 tools schema 與網路邊界

    典型企業場景:你想讓 Claude Managed Agent 幫你跑 CI/CD、讀內網 Git、打內部 REST / Postgres API,但 不能開公網入站、不能把 Git 暴露出去。這次的 self‑hosted sandboxes + MCP tunnels 更新,基本上就是:

    模型與編排留在 Anthropic,工具執行與資料存取拉回你自己的 VPC,且只用安全出站連線。

    實務上等於多了一種選擇:不用把模型拉進內網自建 inference,也能在嚴格邊界內讓 Agent 控制 CI、讀 repo、查 DB。


    重點說明:架構與安全邊界怎麼畫

    1. Orchestrator vs Tools:誰在外面、誰在裡面?

    Claude Managed Agents 大致拆成兩層:

    1. Orchestrator(Anthropic 端托管)
    2. 理解使用者意圖、規劃步驟、決定要叫哪些工具。
    3. 透過 MCP 協定 呼叫你定義的 tools(MCP server)。

    4. Tools / MCP servers(你自己控制)

    5. 例如:git、CI/CD runner、Postgres、內部 REST API
    6. 可以跑在 self‑hosted sandbox 裡(受控容器/VM),或直接在你內網 VPC。

    💡 關鍵: Orchestrator 永遠只看得到你暴露出的 MCP tools 與其 I/O,真正的 Git / DB 資料面與執行權都留在你 VPC。

    關鍵:Orchestrator 看不到你的 Git/DB,只能透過你暴露出的 MCP tools 操作,權限由你決定。


    2. MCP 協定與 server:最小必須心智模型

    MCP server 就是一個會講 JSON‑RPC over stdio / WebSocket 的後端,向 Agent 宣告自己有哪些工具。概念類似「強 typing 的 function calling」。

    一個簡化版的 MCP server schema(YAML)可能長這樣:

    name: corp-dev-tools
    version: 0.1.0
    
    tools:
      - name: git_read_file
        description: 讀取內部 Git repo 某個檔案內容
        input_schema:
          type: object
          required: [repo, path, ref]
          properties:
            repo: { type: string }
            path: { type: string }
            ref:  { type: string }
    
      - name: ci_trigger_pipeline
        description: 觸發 CI pipeline,只能在 allowlist 專案上執行
        input_schema:
          type: object
          required: [project, branch]
          properties:
            project: { type: string }
            branch:  { type: string }
    

    Agent 端會看到 明確的工具清單與參數結構,再決定何時呼叫。


    3. Self‑hosted sandbox:把「程式執行權」留在自己這邊

    self‑hosted sandbox 解決的是:「我不想讓 Anthropic 直接在他們 infra 上跑 shell / Python,請改在我 VPC 裡跑」。

    實作上可以是:

    • 一個專用 k8s namespaceFargate / VM,跑 Anthropic 提供的 sandbox runtime。
    • Agent 要執行程式碼(例如跑單元測試、lint、git 操作),會透過安全通道把 code / 指令丟到這個 sandbox。

    典型邊界設計:

    • sandbox 只能出站連到:
    • 你的 Git / CI / DB / 內部 API
    • Anthropic 的 MCP tunnel endpoint
    • 不能直連其他敏感系統(或至少預設 deny)。

    實際好處: Agent 可以幫你跑 pytest、打 CI webhook、改 Git branch,
    但所有「可以執行程式碼的環境」都在你的控制下,方便做防火牆、資安掃描、審計。


    4. MCP tunnels:如何在不開洞的情況下連到內網

    MCP tunnel 解決:「我的 MCP server 在 VPC 裡,如何讓 Anthropic 托管的 Agent 打到它,但我不願意開入站 443?」

    典型拓撲:

    [Anthropic Orchestrator]
            ^
            | (MCP over tunnel)
            v
    [MCP Tunnel Client in VPC] ----> [MCP Server + Sandbox]
              (outbound TLS)
    

    關鍵特性:

    • 只有 VPC → Anthropic 的出站連線(類似反向隧道)。
    • 隧道建立後,Anthropic 端像是在打本地 MCP server,但實際流量是經由你建立的 mutual TLS / token 隧道轉回來。
    • 容易套用零信任思路:每條隧道都視為一個 identity,綁定最小權限的一組 tools。

    💡 關鍵: 只用出站隧道與 mTLS,就能在不開任何入站 port 的前提下,把內網工具安全地接給 Managed Agent 用。


    實作範例:VPC 內最小可行架構

    場景:

    • VPC 內:
    • 一台 MCP server + sandbox Pod/VM。
    • 連得上 GitLab、Postgres、內部 https://api.intra
    • 出站:允許打到 Anthropic 的 MCP tunnel endpoint

    1. MCP server:Git + Postgres + REST API

    以 Node.js 為例(pseudo‑code):

    import { MCPServer } from "@anthropic-ai/mcp-sdk";
    import { execSync } from "node:child_process";
    import { Client } from "pg";
    import fetch from "node-fetch";
    
    const gitAllowlist = ["service-a", "service-b"];
    
    const server = new MCPServer({ name: "corp-dev-tools" });
    
    server.tool("git_read_file", async ({ repo, path, ref }) => {
      if (!gitAllowlist.includes(repo)) {
        throw new Error("repo not allowed");
      }
      const base = "/srv/git/" + repo;
      const content = execSync(`git --git-dir=${base} show ${ref}:${path}`, {
        encoding: "utf8",
      });
      return { content };
    });
    
    server.tool("db_read_customer", async ({ id }) => {
      const client = new Client({
        host: process.env.PG_HOST,
        user: "readonly_agent",
        password: process.env.PG_PWD,
        database: "app",
        ssl: true,
      });
      await client.connect();
      const res = await client.query("SELECT id, name, status FROM customers WHERE id=$1", [id]);
      await client.end();
      return { rows: res.rows };
    });
    
    server.tool("call_internal_api", async ({ path, method, body }) => {
      if (!path.startsWith("/public-agent/") || method !== "POST") {
        throw new Error("not allowed");
      }
      const resp = await fetch(`https://api.intra${path}`, {
        method,
        headers: { "Authorization": `Bearer ${process.env.AGENT_TOKEN}` },
        body: JSON.stringify(body ?? {}),
      });
      const json = await resp.json();
      return { status: resp.status, data: json };
    });
    
    server.listen();
    

    重點:

    • gitAllowlist:避免 Agent 任意讀所有 repo。
    • Postgres 使用 readonly_agent 帳號,限制只讀特定 schema。
    • 內部 API 降到 /public-agent/ 子路徑 + 專用 token。

    2. MCP tunnel client:出站連上 Anthropic

    實際指令會以官方 CLI / container 為主,概念配置類似:

    anthropic-mcp-tunnel \
      --mcp-url=http://localhost:8000 \
      --agent-id=corp-ci-agent \
      --tls-cert=/etc/mcp/cert.pem \
      --tls-key=/etc/mcp/key.pem \
      --anthropic-endpoint=https://mcp-tunnel.anthropic.com \
      --tags=env:prod,scope:ci
    

    在 Anthropic 控制台,你會:

    • 建立一個 Managed Agent:corp-ci-agent
    • 只綁定這條 tunnel 曝露的 corp-dev-tools MCP server。
    • 開啟前人工審閱 / 部分工具 auto‑approve(視風險)。

    3. ACL 與工具權限設計

    簡單的 policy‑as‑code 思路:

    agent: corp-ci-agent
    allowed_tools:
      - git_read_file
      - ci_trigger_pipeline
      - db_read_customer
      - call_internal_api
    
    constraints:
      git_read_file:
        repos: ["service-a", "service-b"]
        max_file_size_kb: 256
    
      db_read_customer:
        max_rows: 1
    
      call_internal_api:
        allowed_paths:
          - "/public-agent/deploy"
          - "/public-agent/status"
    

    你可以在 MCP server 裡讀這個 YAML,做額外校驗。不要把 ACL 寫死在 prompt 裡,防禦提示注入要靠程式碼與網路邊界。


    建議與注意事項:安全坑與實務整合

    1. 工具權限過大 = Agent RCE 風險

    OWASP Agent Top 10 已經把 工具濫用 / 權限濫用 列為前幾名風險。常見錯誤:

    • 一個 tool 可以執行任意 shell、對任何 DB 下任意 query。
    • Agent 可以打到整個內網,而不是只打 CI / Git / API Gateway。

    建議:

    • 一個 tool 做一件小事,強 schema,避免 free‑form SQL / shell。
    • DB 使用 只讀 + row‑level / column‑level policy
    • 網路上用 安全群組 / SG 把 sandbox 能打的 IP 段鎖死。

    2. 審計 / Logging:要記「自然語言意圖 + 工具調用」

    很多企業只有 infra log,缺少「Agent 為什麼要做這件事」的上下文。

    建議最低標準:

    • 針對每次工具呼叫記錄:
    • user_id / session_id
    • Agent 看到的 自然語言任務描述(可脫敏)
    • 工具名稱 + input 參數(敏感欄位做 partial redaction)
    • 執行結果摘要 / status code

    這樣在事後對齊 OWASP 事件分析時,才能把「提示注入 → 工具濫用 → 資料外洩」串成一條 timeline。


    3. 網路與認證:守住 MCP 隧道與 secrets

    重點:把隧道視為一個高價值通道,跟 VPN 一樣認真看待。

    具體建議:

    • 隧道一律走 mTLS,cert 由內部 CA 或雲端 CA 管理。
    • 隧道 client 的 API token / cert 放在 Vault / KMS,sandbox 上只拿短期 lease。
    • 工具裡 不要回傳 secrets(例如整個 JWT 與 DB 密碼)到 Agent,必要時只在 server 端使用。
    • 若擔心 API key 滲透,在 sandbox 層加 egress proxy,對外送出的 HTTP header 做檢查 / scrub。

    4. 與 SOAR/服務目錄/Secrets 管理整合的實務問題

    實務上會遇到:

    • SOAR / ticket 系統
    • 建議把「開 ticket / 查告警 / 執行 playbook」封裝成 MCP tools,權限沿用既有 RBAC。

    • 服務目錄(例如 Backstage)

    • MCP tools 可以讀服務目錄 API,讓 Agent 知道 repo 屬於哪個團隊、能不能改 config。

    • Secrets 管理(Vault/KMS)

    • 不要給 Agent 直接讀 Vault 的能力;改由 MCP tool 在 server 端解密,對 Agent 只暴露結果(或再加工)。

    5. 和「模型拉進內網自建 inference」的取捨

    Managed Agent + self‑hosted sandbox + MCP tunnel:

    • 優點:
    • 不用自己跑 LLM cluster,只負責工具、網路、權限
    • 快速接雲端最新模型(含之後像 Mythos 這種安全模型的企業版)。
    • 合規上:資料只經由 tools 進出,你可以精準監控。

    • 缺點:

    • Orchestrator 還是在 Anthropic,那邊仍會看到 工具 I/O 摘要
    • 對極端資料主權(完全不能出域)的場景不適合。

    自建 inference:

    • 優點:
    • 完整掌控模型與權限,所有 token 在你網段內。

    • 缺點:

    • 要自己做 Agent orchestration、tooling、guardrail、OWASP Top 10 風險防護。
    • 成本與維運門檻高。

    如果你目前已在雲上、允許「模型在外、資料在內」,這次的 Claude Managed Agents 私有化能力 是一個相對平衡的折衷:

    把最麻煩的 LLM 與 Agent orchestration 交給 Anthropic,把最敏感的程式執行與資料權限留在 VPC,用 MCP + sandbox 畫清楚邊界。

    🚀 你現在可以做的事

    • 在現有 VPC 內起一個簡單 corp-dev-tools MCP server(照文中 Node.js 範例改成你公司的 Git / DB / API)
    • 部署 anthropic-mcp-tunnel 類似的隧道 client,實測只用出站連線即可讓 Managed Agent 操作內網工具
    • 寫一份 YAML ACL(如文中 policy‑as‑code 範例),把 repo / DB / API 權限具體收斂後再開放給 Agent 使用
  • Symphony 與自管 Agent 的技術拆解

    Symphony 與自管 Agent 的技術拆解

    📌 本文重點

    • 讓 Agent 主動拉工單並自排程,減少工程師 babysit
    • 採用混合 Multi-Agent 模式與明確權限邊界
    • 透過 Task Queue + Worker + 審批閘門串起從工單到 PR 的全流程

    人類注意力已經成為工程團隊採用 AI 助手的主要瓶頸:Agent 能寫 code,但你要一直盯著它。Symphony 類的自管 Agent 系統,直接改變的是這件事:

    從「工程師 babysit 多個 Agent」→「Agent 自己從 Linear / Jira 拉工單、自排程、跑完整個 CI/CD pipeline,只在關鍵節點請你按一次 Approve」。

    下面從實作角度拆解:如何設計任務拉取、Multi-Agent workflow、與 CI/CD 權限邊界;最後給一個「自動修 bug → 開 PR → 回寫 Linear 狀態」樣板。


    重點說明

    1. 工單拉取與任務自排程

    核心是讓 Agent 變成一個長壽命 worker,定期從任務池拉工單,而不是被動等待 API 呼叫。

    工單來源

    • Linear: /issues, /webhooks, /comments
    • Jira: /rest/api/3/search, /rest/api/3/webhook

    Polling vs Webhook

    • Polling(簡單好 Debug)
    • 優點:
      • 實作簡單,只要定時 cron + API token
      • 不怕 webhook misconfig / 防火牆問題
    • 缺點:

      • 有延遲(30s–5min)
      • 需要自己做去重 / 任務狀態同步
    • Webhook(推薦長期方案)

    • 優點:
      • 事件即時觸發,適合高優先 bug / incident
      • 可根據事件類型直接分路由(bug vs feature)
    • 缺點:
      • 需要公開 endpoint + 驗簽
      • 部署與權限設定更複雜

    實務上常用 混合策略

    • Webhook 處理新建 / 更新事件
    • Polling 每隔 5–10 分鐘做 reconcile,修正漏觸發 / 失敗同步

    💡 關鍵: 用「Webhook 即時 + 每 5–10 分鐘 Polling 校正」的混合策略,可以在保持即時性的同時降低漏事件風險。

    任務分派與併發控制

    • 任務表核心欄位建議:
    • id, source(issue_id), priority, status(queued/running/failed/done), agent_type, lock_owner, lock_expires_at
    • 分派策略可以簡化成:
    • 優先級隊列:依 Linear priority / label 映射成數值
    • 技能匹配:根據 label → agent_type(例如 frontend, backend, infra

    併發與重試控制的關鍵:樂觀鎖 + visibility timeout

    -- 簡化的任務鎖定 SQL
    UPDATE tasks
    SET status = 'running', lock_owner = :agent_id, lock_expires_at = NOW() + interval '15 minutes'
    WHERE id = (
      SELECT id FROM tasks
      WHERE status IN ('queued', 'failed')
        AND (lock_expires_at IS NULL OR lock_expires_at < NOW())
      ORDER BY priority DESC, created_at ASC
      LIMIT 1
      FOR UPDATE SKIP LOCKED
    )
    RETURNING *;
    

    好處

    • 避免多個 Agent 搶同一張工單
    • Agent 崩潰 / timeout 時,lock 過期後可被其他 Agent 接手(類似 SQS visibility timeout)

    2. Multi-Agent:中心協調 vs 任務接力

    現代多 Agent 系統基本都落在兩種模式上(參考 Agents as Tools vs Handoffs)。

    模式 A:中心協調(Agents as Tools)

    • 一個「指揮官」Agent + 多個「工具」Agent
    • 主 Agent 保留全局 context 與決策權,子 Agent 像 function call

    • 示意(虛擬 code):

    const orchestrator = new OrchestratorAgent({
      tools: {
        codeAgent: callCodeAgent,
        testAgent: callTestAgent,
        infraAgent: callInfraAgent,
      }
    });
    
    await orchestrator.run({
      goal: "Fix bug #123 in service A and deploy to staging",
      constraints: { require_approval_for_deploy: true }
    });
    

    適合

    • 需求不明確,需要動態拆解子任務
    • 需要統一治理(quota、安全策略、審計)

    模式 B:任務接力(Handoffs)

    • 任務隨流程在 Agent 之間流動
    • 每個 Agent 處理完就寫結果 + 下一步指派
    // task.payload 示例(存在 DB / Task Queue)
    {
      "status": "code_fixed",
      "next_agent": "test_agent",
      "artifacts": {
        "branch": "fix/BUG-123-null-pointer",
        "diff_summary": "..."
      }
    }
    

    適合

    • Pipeline 已穩定(bugfix → test → PR → notify)
    • 易於水平擴展,每個 Agent 是一組 worker

    實務建議:多數專案採用 混合

    • 一個 中心協調 Agent,但遇到標準化步驟(跑測試、開 PR、通知 Slack)時,交給 固定 handoff stage 的 worker;類似「主流程由 LLM 控制,heavy lifting 由 deterministic step 執行」。

    💡 關鍵: 把「決策」交給中心協調 Agent,把「重複且標準化的步驟」交給固定 worker,可以在保持靈活度的同時確保穩定性與成本可控。


    3. 與 CI/CD、code review、事故流程整合

    自管 Agent 的威力,取決於你如何設計 權限邊界 + 審批閘門

    權限邊界設計

    • Repo 層級:
    • 建立專用 GitHub App / GitLab Token,只開放:
      • repo:contents:write(但限制特定 org / repo)
      • pull_request:write
    • 禁止直接 push main / production branch
    • 環境層級:
    • Agent 只允許:
      • Deploy 到 staging / preview env
      • 觸發 read-only incident tooling(查 log、查 metrics),不要一開始就給 rollback / scale 權限

    審批閘門(approval gate)

    • 在 CI pipeline 加一個手動 stage,例如 GitHub Actions:
    jobs:
      tests:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - run: npm test
    
      deploy_staging:
        needs: tests
        if: github.actor == 'agent-bot'
        environment:
          name: staging
          # GitHub Environments 的 Reviewers 即是 approval gate
        steps:
          - run: ./deploy-staging.sh
    

    審計 log

    • 每個關鍵行為都應落地:
    • 取得工單(issue_id, agent_id, reason, time
    • 對 repo 的修改(branch, commit_sha, diff_summary, tests_run
    • 任何 CI/CD trigger(workflow_id, inputs, result

    • 建議統一經過一個 AuditService.log(event)

    await AuditService.log({
      actor: "agent-bot",
      action: "CREATE_PR",
      metadata: {
        issue_id: "ENG-1234",
        repo: "org/service-a",
        branch: "fix/ENG-1234-null-pointer",
        pr_url: "https://github.com/..."
      }
    });
    

    💡 關鍵: 把權限鎖在「staging + PR 層級」並配合審批閘門與審計 log,可以在不影響生產安全的前提下,讓 Agent 最大化自動化範圍。


    實作範例:從 Linear 抓 bug → 開分支 → 修 code → 開 PR → 回寫狀態

    以下是一個縮小版 blueprint,你可以直接改成自家 stack。

    1. 任務入口:Linear Webhook + 任務表

    Linear Webhook 指向你的 /linear/webhook

    // Express 風格
    app.post('/linear/webhook', async (req, res) => {
      const event = req.body;
    
      if (event.type === 'IssueCreated' || event.type === 'IssueUpdated') {
        const issue = event.data;
    
        // 僅處理 bug + 特定 team
        if (issue.team.key === 'ENG' && issue.labelNames.includes('bug')) {
          await TaskRepo.enqueue({
            source: 'linear',
            source_issue_id: issue.id,
            priority: mapLinearPriority(issue.priority),
            agent_type: 'bugfix',
            status: 'queued'
          });
        }
      }
    
      res.sendStatus(200);
    });
    

    2. Bugfix Agent Worker(核心 loop)

    async function bugfixWorkerLoop() {
      while (true) {
        const task = await TaskRepo.acquireNext('bugfix', process.env.AGENT_ID);
        if (!task) {
          await sleep(5000);
          continue;
        }
    
        try {
          const issue = await LinearApi.getIssue(task.source_issue_id);
          const repo = mapIssueToRepo(issue);
          const branch = `fix/${issue.identifier}-${slug(issue.title)}`;
    
          await GitService.createBranch({ repo, from: 'main', branch });
    
          const diff = await CodeAgent.fixBug({
            repo,
            branch,
            issue_description: issue.title + '\n\n' + issue.description,
            files_hint: inferRelatedFiles(issue)
          });
    
          await GitService.commitAndPush({ repo, branch, message: `fix: ${issue.identifier}` });
    
          const pr = await GitService.createPR({
            repo,
            branch,
            base: 'main',
            title: `[Agent] Fix ${issue.identifier}: ${issue.title}`,
            body: renderPRBody(issue, diff)
          });
    
          await LinearApi.updateIssue(task.source_issue_id, {
            state: 'In Review',
            descriptionAppend: `\n\nLinked PR: ${pr.url}`
          });
    
          await TaskRepo.markDone(task.id);
        } catch (err) {
          await TaskRepo.markFailed(task.id, { error: String(err) });
        }
      }
    }
    

    關鍵點

    • CodeAgent.fixBug 本身可以是一個 Symphony / Claude Managed Agent:
    • 有自己的工具:get_file, apply_diff, run_tests
    • 有自己的「Outcomes」條件(例如:測試必須綠燈、diff 不能超過 500 行)
    • Worker loop 要能容錯:task failure 不要直接 crash process

    3. 錯誤恢復與常見坑

    (1) stale context / 版本衝突

    • 現象:Agent 基於舊 commit 生成 patch,push 時發現 remote 已有新 commit
    • 對策:
    • createBranch 前先 git fetch + 檢查 main 是否有新 commit
    • 若有衝突,改用 rebase + 再跑一次 CodeAgent,或直接加標籤請人工處理

    (2) 任務飢餓(某些工單一直排不到)

    • 常見原因:
    • 單純用 FIFO,長工時任務卡住隊列
    • 高 priority 任務一直插隊
    • 對策:
    • 採用 優先級 + aging:等待時間越久,自動提高 effective priority
    • 給長任務單獨的 queue 或 agent_type

    (3) 被動等待人工決策,Agent 資源被佔住

    • 例如:Agent 開 PR 後要等 Reviewer,期間 worker 就 idle with lock
    • 對策:
    • 把「等待人工」拆出成另一個狀態:
      • 任務設為 status = waiting_human
      • PR merge / Linear 狀態變更時再由 webhook 建下一個 task(例如 deploy)

    (4) AI 決策不穩(修了錯問題)

    • 這是現在 Agent 最大痛點之一(參考「AI is getting better at doing things, but still bad at deciding what to do」)。
    • 對策:
    • CodeAgent 設定明確 Outcome 定義
      • 測試要準備好一組 reproduction test
      • 用獨立 Evaluator Agent 根據 log / diff 給出 pass / needs-clarification
    • 讓 Agent 更常問問題:若重現步驟不完整,直接在 Linear 開 comment 要求補充,而不是盲修。

    建議與注意事項

    1. 從「觀察型 Agent」開始,不要一開始就給寫入權限

    2. 先只允許:讀工單 → 產生修復方案 / diff 草稿 → 貼回 Linear。穩定後再打開 PR 寫入、最後才接 CI/CD。

    3. 集中化審計與開關

    4. 所有 Agent 行為走一個 Agent Gateway / Orchestrator,集中:

      • 配額控制
      • 風險開關(feature flag 一鍵關掉所有 auto-deploy)
      • log / metrics / alert
    5. 明確定義「哪一段流程可以 0 人工」

    6. 常見安全配置:

      • bugfix PR 可以由 Agent 全自動產生,但 merge 必須人工
      • staging deploy 可自動,production deploy 必須經 Slack / PagerDuty approve
    7. 將 Agent 視為「非穩定服務」而非傳統微服務

    8. 接受它偶爾會做奇怪決策,因此整個系統必須:

      • 有清楚的 rollback 路徑
      • 任務永遠由 queue 控制,不綁死在單一 process
      • 重要資源(code、infra)永遠有 versioning + 審批

    如果你已經有 Linear / Jira + GitHub + CI/CD 的基本骨架,其實不用重建世界:

    只要加上一個 Task Queue + Agent Worker + 守門的 Orchestrator/Approval Gate,你就能讓 Symphony 類的自管 Agent 為團隊接手一條完整的「從工單到 PR」流水線,真正從盯著 Agent 寫 code,變成只盯少數關鍵決策點。

    🚀 你現在可以做的事

    • 在現有 Linear / Jira 加一個 Webhook,寫入自建的 tasks 資料表作為任務池
    • 實作一個最小版 bugfixWorkerLoop,先只產生修復方案與 diff 草稿貼回工單
    • 在 CI/CD 中加入只對 agent-bot 生效的 staging deploy job,並配置 GitHub Environments 審批閘門