Last updated on

copilot-agent-lite 设计模式:YAML agent + cron + MCP


设计动机:Copilot SDK + 全自动化调度

GitHub Copilot 的 AI Agent 能力在 2025 年事实上已达到生产可用,但手动触发仍是主要使用模式。Codex CLI、Claude Code……都需要用户在终端前手动输入指令。

copilot-agent-lite 要回答的问题是:

能不能让 Copilot Agent 自己定时去跑,不依赖人去敲键盘?

答案是肯定的。但设计上需要一个”框架”让 YAML 配置 → Agent 执行 → MCP 传递成为一条可观测的流水线

# ─── 一行命令启动 ───
uvicorn main:app --reload
# → Swagger UI http://localhost:8000/docs
# → Cron 调度在后台静默运行

核心设计架构

schedule.yaml ──→ APScheduler ──→ Executor ──→ Copilot SDK ──→ MCP Tools ──→ SQLite DB

              (YAML agent definitions)

三层解耦:Cron 调度层、执行引擎层、MCP 透传层;任何一层都可以单独替换,不需要改动其他两层。

YAML Agent 定义

# agents/security-scan.yaml
name: security-scan
description: "扫描 PR 中的安全敏感信息"

steps:
  # 1. Copilot 用自有代码Completion能力 reads a diff
  - action: copilot_completion
    input: |
      Review this PR diff for hardcoded credentials,
      exposed API keys, and SQL injection risks:
      
      Diff:
      {{ diff_from_github_api }}
      
    output: findings_report

  # 2. 提取结构化发现写回 DB
  - action: python_snippet
    code: |
      from db import save_findings
      save_findings(findings_report.parse_json())

YAML 是声明式的,不是脚本。这允许分隔:谁来 YAML 写配置(工程团队),谁来维护 Python 执行引擎(核心开发)。

FastAPI Executor

# src/run.py
import yaml
from copilot_sdk import CopilotAgent
from apscheduler.schedulers.asyncio import AsyncIOScheduler

scheduler = AsyncIOScheduler()

def load_agent(path: str) -> dict:
    with open(path) as f:
        return yaml.safe_load(f)

async def execute_step(agent_cfg: dict, step: dict):
    action = step["action"]

    if action == "copilot_completion":
        return await CopilotAgent.chat(step["input"])

    elif action == "python_snippet":
        # sandboxed exec
        return sandbox_run(step["code"], context)

    elif action == "mcp_tool_call":
        return await mcp_proxy.tool(step["tool"], step["params"])

@app.post("/agents/{name}/run")
async def run_agent(name: str, request: RunRequest):
    cfg = load_agent(f"agents/{name}.yaml")
    result = await execute_steps(cfg, request.context)
    await db.log_result(name, result)
    return result

MCP Server 透明透传

# MCP tool 包装成 copilot-agent-lite 执行步骤
async def mcp_proxy_tool(tool_name: str, params: dict):
    # copilot-agent-lite 知道 MCP endpoint
    endpoint = settings.mcp_servers[tool_name].endpoint

    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{endpoint}/tools/execute",
            json={"name": tool_name, "arguments": params},
            headers={"Authorization": f"Bearer {settings.mcp_api_key}"},
        )
    return resp.json()

路径透明:User → agent YAML → interpreter → MCP 协议 → MCP 服务端(e.g. a GitHub MCP 服务)。对 copilot-agent-lite 来说,MCP 只是另一个执行步骤。

Cron 调度

# src/schedules.yaml
schedules:
  - agent: security-scan
    cron: "0 9,18 * * 1-5"   # 工作日 9:00 / 18:00
    context:                  # 触发时注入上下文
      diff_from_github_api:
        _branch: "main"
        _compare: "origin/main"
        _repo: "openai/copilot-agent-lite"

  - agent: daily-code-review
    cron: "0 10 * * 1-4"     # 周一至周四 10:00
# 动态加载而不重启服务
@app.post("/schedules/reload")
async def reload_schedules():
    with open("schedules.yaml") as f:
        schedules = yaml.safe_load(f)
    scheduler.remove_all_jobs()
    for s in schedules["schedules"]:
        scheduler.add_job(
            run_agent_from_schedule,
            "cron",
            args=[s],
            **cron_to_kwargs(s["cron"]),
        )
    return {"reloaded": len(schedules)}

资源清单:这个东西有多轻?

组件数量说明
外部 broker0没有 RabbitMQ / Redis
容器化uvicorn main:app 直接跑
配置文件1schedules.yaml
云依赖本地运行,self-hosted
pip dependencies~8fastapi, uvicorn, apscheduler, httpx …
k8s / Docker不需要纯 Python

没有 RabbitMQ · 没有 Redis · 没有 LangChain · 删掉 k8s,只有 pip install + uvicorn main:app。

下一步迭代

  • 已发布:YAML agent 执行引擎 + MCP 透传
  • ⏳ Q3 2025:Docker Hub 一键镜像
  • ⏳ Q3 2025:Telegram 异常告警
  • ⏳ Q4 2025:GitHub Actions action 版本
git clone https://github.com/bbfans/copilot-agent-lite
cd copilot-agent-lite
pip install -r requirements.txt
uvicorn main:app --reload