目录

怎样让本地 AI CLI 对外服务?——从claude起点看ACP

很多人现在都把本地 AI CLI 用起来了:

  • Claude CLI
  • Codex
  • 自己用比如 LangGraph 做的工具

然而,这些 CLI,默认是「只能自己使用」的。

如果想要把这些工具共享给团队共同使用,该怎么办?

这篇文章,我们从 Claude CLI 出发,来讲讲这件事:

如何让“本地 AI CLI”变成“对外服务”

一、交互式程序

当我们打开terminal,输入 claude 命令,便启动了一个 claude 会话。

你输入一句话:

查看当前分支的改动,检查是否有风险

它过一会返回结果,或是进行提问,进行多轮对话后返回结果。

问题:它是一个「交互式程序」,不是服务。

  • 没有API
  • 没有统一协议
  • 没有外部调用入口

二、套一层HTTP?

于是,第一反应是:

我给它套一层HTTP不就行了?

当然可以:

@app.post("/chat")
def chat(q: str): 
    return run_claude_cli(q)

然而,很快会遇到问题:

  1. 难以支持多轮对话:CLI 的上下文是黑盒,难以控制 session
  2. 难以完成工具调用:例如 AI 想调用 shell 时,你不知道它在干什么
  3. 难以做审批/控制

因此,这种方式只能简单地「远程调用一次 CLI 」,复杂些的任务难以完成。

三、官方 SDK

Claude 官方提供了 SDK:https://platform.claude.com/docs/en/agent-sdk/overview

import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions


async def main():
    async for message in query(
        prompt="Find all TODO comments and create a summary",
        options=ClaudeAgentOptions(allowed_tools=["Read", "Glob", "Grep"]),
    ):
        if hasattr(message, "result"):
            print(message.result)


asyncio.run(main())

因为是官方出品,使用体验还是不错的。

查看源码可知,它实际上也是调用本地的 Claude-CLI:

    def _find_cli(self) -> str:
        """Find Claude Code CLI binary."""
        # First, check for bundled CLI
        bundled_cli = self._find_bundled_cli()
        if bundled_cli:
            return bundled_cli

        # Fall back to system-wide search
        if cli := shutil.which("claude"):
            return cli

        locations = [
            Path.home() / ".npm-global/bin/claude",
            Path("/usr/local/bin/claude"),
            Path.home() / ".local/bin/claude",
            Path.home() / "node_modules/.bin/claude",
            Path.home() / ".yarn/bin/claude",
            Path.home() / ".claude/local/claude",
        ]

        for path in locations:
            if path.exists() and path.is_file():
                return str(path)

        raise CLINotFoundError(
            "Claude Code not found. Install with:\n"
            "  npm install -g @anthropic-ai/claude-code\n"
            "\nIf already installed locally, try:\n"
            '  export PATH="$HOME/node_modules/.bin:$PATH"\n'
            "\nOr provide the path via ClaudeAgentOptions:\n"
            "  ClaudeAgentOptions(cli_path='/path/to/claude')"
        )

更具体的关于它是如何通过调用本地 cli 来完成各种任务的细节我没有去细看了,总之通过官方 SDK 的方式可以实现非常优雅地调用 Claude 各种功能,然后在外部暴露几个接口即可。具体方法大家查阅官网即可。

于是下一个问题出现:

我们如果决定不再使用 Claude,换成 codeX,这些代码又要重写一份吗?

四、ACP

ACP(Agent Client Protocol)是一种让 Agent 与 Agent 之间交互的一种协议。

它类似于:

  • HTTP 之于 Web
  • gRPC 之于 微服务

ACP 把 Agent 交互所需的信息都整理出来结构化,只要各家 Agent 都遵守这个协议,那么切换 Agent 就只需要改个配置,其他逻辑都是一模一样的。

https://github.com/agentclientprotocol

ACP 做了什么?

ACP 定义了一些对于 Agent 非常关键的事情,例如:

  1. Session
{ "session_id": "xxx" }
  1. Message
{
  "role": "assistant", 
  "content": "..." 
}
  1. Tool Call
{ 
  "type": "tool_call", 
  "name": "bash", 
  "arguments": {...}
}

以及中断、审批等等等等。

ACP 现在还在快速迭代中,但就像 MCP 一样,一定是 AI 时代非常重要的一个协议。

我们在实现自己的 Agent 时( Server )或者是调用 Agent 的工具时( Client ),用 ACP 来实现,维护起来会事半功倍。

五、从 CLI 到服务的一种架构

于是我们梳理出一个从 CLI 到服务的架构,其实很简单:

外部请求(飞书 / 企微 / API) 
       │ 
       ▼ 
       你的网关服务 
       │ 
       ▼ Agent(ACP 协议) 
       │ 
       ├── Claude / LLM 
       └── 工具系统(MCP / HTTP / DB / Shell)

六、趋势

别再停留在写 Prompt 的版本了,让 AI 接入真实系统已经是我们不得不必须具备的能力。

如果你一直在观望或者刚刚起步,希望本文能成为你的起点。