Show HN:Aclif——面向 Agent 的 CLI 框架,以统一语法和规范名称覆盖 SaaS
英文标题:🔶 Show HN: Aclif – Agent CLI framework: one grammar, canonical names across SaaS
Aclif 是一个面向 AI Agent 的命令行工具框架,旨在通过统一的命令语法、JSON 返回封装和错误词汇,连接 Salesforce、ServiceNow 等不同 SaaS 平台。其核心设计是按需加载命令定义,避免像 MCP 工具列表那样持续占用 Agent 上下文,同时允许 Agent 在设计阶段确定命令、在运行阶段无推理地直接执行。框架提供规范名称映射、无需执行即可进行的命令自省、可声明的安全元数据,以及适用于 Agent、宿主应用和网关的三种运行方式。对于企业部署而言,网关模式可集中管理凭据、策略、用户身份和审计记录,并让多个 Agent 共享统一的跨平台操作接口。
19.8 KB
中文
Agent CLI 框架
aclif 为 AI Agent 构建命令行工具。Agent 获得一个工具,即可通过统一抽象访问所有 SaaS 提供商:一套语法,以及规范名称;在任何平台上,均可通过同一个名称访问同一条记录。
立即试用
安装二进制文件,列出提供商,并读取命令的 Schema、示例和安全元数据。
npm install -g @aclif/core
aclif discover --json
aclif learn salesforce --json
aclif learn servicenow --json
aclif salesforce data query --schema
aclif salesforce data query --examples
aclif salesforce data query --query "SELECT Id FROM Account LIMIT 3" --dry-run
aclif servicenow data query --table incident --query "active=true^priority=1" --dry-run
为什么 Agent 需要自己的 CLI
MCP 服务器会发布一组固定工具,且列表中的每个工具都会在每一轮中占用 Agent 的上下文。服务器作者必须在构建服务器时,在覆盖范围与成本之间取舍。发布全部操作(一个典型 API 有数百个定义)可使整个 API 都能被访问,但每一轮都会为全部操作消耗 Token。只发布少数宽泛操作可以保持较低的 Token 数量,但作者未列出的任何操作都将无法被 Agent 访问。一个跨越多个平台的 Agent,需要为每个平台配置服务器、登录方式、语法、错误格式和一组名称。
aclif 只在 Agent 请求某个命令时加载其定义,因此每个提供商的完整 API 都可访问,且不会持续占用上下文。所有提供商共用一套语法、一个封装格式和一组错误词汇,因此无论 Agent 访问一个平台还是五个平台,其上下文规模都大致相同。
执行既定工作流的 Agent 可以完全不让模型参与调用。人员或创作工具会在设计阶段确定精确命令,并将其作为字符串嵌入工作流。运行时,Agent 将该字符串作为普通代码执行,无需加载工具定义,也无需推理。命令在设计阶段选定;执行权限、凭据、执行身份和策略,则在运行阶段由执行它的环境提供。任何一方都不会同时持有两者。
每个命令提供什么
一套语法
所有提供商共用一种命令结构、一个 JSON 封装格式和一组错误词汇。Agent 只需学习一次工具;新增平台时只会增加命令,而无需新增语法。JSON manifest 可通过一个 HTTP 端点,以相同语法添加命令,无需编写代码。
规范名称
别名集合可在某个 Salesforce 实例中将 customer 映射为 Account,并在 ServiceNow 中映射为 core_company。部署时从各实例采集的租户目录,可让 CLI 学习每个实例的自定义对象和字段,而无需修改提供商实现。
Agent 可以采取行动的错误
Agent 可在一轮内恢复。每个错误都会指出故障原因、可修复该问题的命令,以及在提供商分类器具备针对该错误的重写规则时,提供可直接重新发送的修正输入。该分类器是没有模型参与的普通代码。一个在设计阶段通过 Shell 验证的命令,无论在何种宿主环境中运行,都会在运行阶段返回相同错误,因为两个场景运行的是同一套命令类。
无需执行的自省
--schema、--examples、--shape 及另外四个标志会在命令执行前返回,无需凭据,也不占用 API 配额。Agent 可以针对受限流的实例进行发现、学习、自省和预览,而不消耗任何资源。
可嵌入的运行时
同一套命令类可在进程内运行于宿主环境中;宿主可按请求提供凭据、身份和策略,保持连接预热,并按实例缓存开销高昂的登录操作。基于该运行时构建的网关可对接企业自身的身份提供商和密钥库。
已声明的安全性
每个命令都声明其可变性、影响范围、可逆性和幂等性。策略检查可在命令代码加载前拒绝执行。每个变更操作都接受 --dry-run;元数据要求确认时则必须传入 --confirm;每次运行后都会写入一条审计记录。
自省优先的工作流
除二进制文件外,Agent 无需任何文档;且在最后一步之前,没有任何操作会触及 API。
aclif discover --json # every provider, its tier, whether credentials are configured
aclif learn salesforce --json # a briefing: topics, key fields, query syntax, auth paths
aclif salesforce data query --schema # flags, args, safety metadata, no execution
aclif salesforce data query --examples # runnable examples with the responses they produce
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 5" --dry-run
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 5" --json
封装结果中的 _context 区块包含分页信息及精确的下一条命令、可用字段,以及值得运行的相关命令。退出代码分别为:0、1(API)、2(用法)、3(认证)。相关约定及 JSON Schema 见 CONTRACT.md。
三种运行方式
供应商 CLI 是为单一部署模式构建的:安装在一台机器上,由键盘前的人员登录,每条命令对应一个进程。但在网关之后,这种模式会失效:每次调用都会启动一个进程并重新登录,无法转发实际执行用户的身份,没有机制声明命令将执行何种操作,也没有统一的审计方式。aclif 的命令类可不经修改地在三个位置运行,而运行它的一方决定由谁提供凭据、执行策略以及维护审计轨迹。
- 由 Agent 运行。 Agent 进程启动二进制文件、执行命令,并读取其返回的 JSON。凭据来自 Agent 自身环境中的标志、环境变量或配置文件。适用于一个 Agent、一个操作员和一组凭据共享同一信任边界的情形。
- 由宿主应用运行,即设计阶段场景。 应用位于模型与 aclif 之间,并持有凭据。模型调用由应用定义的工具;应用在进程内执行命令,或将命令字符串传递给 CLI。人员或创作工具可借此让模型发现提供商、自省命令,并验证其将写入 Agent 的精确命令。适用于模型绝不能持有凭据、且工具定义必须留在模型上下文之外的情形。
- 由网关运行,即运行阶段场景。 已部署的 Agent 提交命令,一个长期运行的进程为许多此类 Agent 提供服务。网关按请求从企业密钥库解析凭据,根据实际执行用户检查策略,记录每次调用,并保持连接预热。Agent 不持有提供商凭据,也无法自行扩大权限范围。适用于多个 Agent 共享提供商、且策略和审计必须集中管理的情形。
| 由 Agent 运行 | 由宿主应用运行 | 由网关运行 | |
|---|---|---|---|
| 凭据 | 标志、环境变量、config.yaml |
宿主提供的解析器 | 由密钥库支持的按请求解析器 |
| 策略 | config.yaml |
capabilityGate hook |
capabilityGate 加宿主中间件 |
| 身份 | --identity-token 或环境变量 |
调用中的实际执行用户 | 请求中的实际执行用户及 SSO 声明 |
| 审计 | 每次运行写入 stderr 的一行 | reporter 事件 | reporter 事件,由宿主记录 |
| 连接 | 文件会话缓存 | 运行时连接池 | 按实例和身份分组的运行时连接池 |
详情见嵌入页面。
网关部署
长期运行、可嵌入的部署方式支持一种可应用额外安全策略的网关拓扑。企业运营的单个进程可为每个 Agent 执行所有命令,并提供:
- 将凭据集中在一处。 凭据在网关内按请求从企业密钥库解析,Agent 不持有任何凭据。
- 企业范围内的规范名称。 租户目录和别名集合由网关维护,因此每个 Agent 都会针对所有提供商和实例中的相同记录使用相同名称。
- 每次调用均归属到具体人员。 实际执行用户的身份会随每次调用进入策略检查和审计记录,即使使用共享服务账户也是如此。
- 策略只执行一次。 每个命令都会声明其将执行的操作,网关在命令代码加载前检查该声明。Agent 无法自行扩大权限范围。
- 一条统一审计轨迹。 所有 Agent 的每条命令都产生同一种事件,其中包含用户、命令和结果。
安装,或构建自己的 CLI
npm install -g @aclif/core
# Your org's My Domain URL, no trailing slash
export SF_INSTANCE_URL=https://example.my.salesforce.com
# A session token from the Salesforce CLI (sf org login web first if needed)
export SF_ACCESS_TOKEN=$(sf org auth show-access-token -o me@example.com --json | jq -r .result.accessToken)
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 3" --json
如果不使用 Salesforce CLI,可使用 API 用户。Salesforce 会在设置或重置密码时通过电子邮件发送安全令牌:
export SF_INSTANCE_URL=https://example.my.salesforce.com SF_USERNAME=me@example.com SF_PASSWORD=... SF_SECURITY_TOKEN=...
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 3" --json
aclif 二进制文件随附所有内置提供商,并要求 Node 22 或更高版本。你发布的二进制文件完全由你控制:一条 scaffold 命令即可生成拥有独立名称、独立配置目录、独立环境变量,并且仅包含所选提供商的 CLI。参见快速入门和构建 CLI。
提供商
Salesforce、ServiceNow、DocuSign 和 Agentforce 为原生支持,并包含在每个版本中。Google Workspace(Gmail、Calendar)由社区贡献。私有层允许 fork 将提供商保留在仅自己使用的路径下,上游永远不会提交该路径。编写一个提供商所需工作量很小:它本质上是将平台 API 规范直接映射到命令表面;编码 Agent 可根据仓库中的示例提示完成此项工作,而一致性测试套件会检查结果。参见提供商。
aclif 采用 MIT 许可证。贡献请遵循 CONTRIBUTING.md;供人员和编码 Agent 修改框架时使用的指南见 AGENTS.md。
English / 原文
The Agent CLI Framework
aclif builds command-line tools for AI agents. An agent gets a single tool that provides a unified abstraction across every SaaS provider: one grammar, and canonical names that reach the same record by the same name on any platform.
Try it now
Install the binary, list the providers, and read a command's schema, examples, and safety metadata.
npm install -g @aclif/core
aclif discover --json
aclif learn salesforce --json
aclif learn servicenow --json
aclif salesforce data query --schema
aclif salesforce data query --examples
aclif salesforce data query --query "SELECT Id FROM Account LIMIT 3" --dry-run
aclif servicenow data query --table incident --query "active=true^priority=1" --dry-run
Why agents need their own CLI
An MCP server publishes a fixed list of tools, and every tool on the list occupies the agent's context on every turn. The server's author trades coverage for cost when the server is built. Publishing every operation (a typical API has hundreds of definitions) keeps the whole API reachable and consumes tokens for all of it on every turn. Publishing a handful of broad operations keeps the token count small, and any operation the author left off the list is out of the agent's reach. An agent that spans several platforms needs a server, a login, a grammar, an error format, and a set of names for each.
aclif loads a command's definition only when the agent asks for it, so the whole API of every provider is reachable at no standing cost in context. One grammar, one envelope, and one error vocabulary cover every provider, so the agent's context stays about the same size whether it reaches one platform or five.
An agent that runs a defined workflow can leave the model out of the call altogether. A person or an authoring tool works out the exact command at design time and embeds it in the workflow as a string. At run time the agent executes that string as ordinary code, with no tool definition loaded and no inference. The command is chosen at design time, and the authority to run it, the credential, the acting identity, and the policy, is supplied at run time by whatever runs it. Neither side ever holds both.
What every command gives you
One grammar
One command structure, one JSON envelope, and one error vocabulary across every provider. An agent learns the tool once, and a new platform adds commands without adding grammar. A JSON manifest adds a command over one HTTP endpoint in the same grammar, with no code.
Canonical names
Alias sets map customer to Account in one Salesforce instance and core_company in ServiceNow. A tenant catalog, captured from each instance at deploy time, teaches the CLI each instance's custom objects and fields with no change to the provider.
Errors an agent can act on
An agent recovers in one turn. Every error names the failure, the command that fixes it, and, where the provider's classifier has a rewrite rule for the mistake, the corrected input ready to resend. The classifier is plain code with no model behind it. A command validated in a shell at design time returns the same error at run time under any host, because the same command classes run in both.
Introspection without execution
--schema, --examples, --shape, and four more flags return before the command runs, need no credentials, and count against no API quota. An agent can discover, learn, introspect, and preview against a rate-limited instance and spend nothing.
An embeddable runtime
The same command classes run in-process inside a host that supplies credentials, identity, and policy per request, keeps connections warm, and caches expensive logins per instance. A gateway built on it works with the enterprise's own identity provider and secrets vault.
Declared safety
Mutability, blast radius, reversibility, and idempotency are declared on every command. A policy check can refuse it before its code loads. Every mutation accepts --dry-run, demands --confirm where its metadata says so, and writes an audit line after every run.
The introspection-first workflow
An agent needs no documentation beyond the binary, and nothing before the last step touches the API.
aclif discover --json # every provider, its tier, whether credentials are configured
aclif learn salesforce --json # a briefing: topics, key fields, query syntax, auth paths
aclif salesforce data query --schema # flags, args, safety metadata, no execution
aclif salesforce data query --examples # runnable examples with the responses they produce
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 5" --dry-run
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 5" --json
The envelope's _context block holds pagination with the exact next command, the fields available, and related commands worth running. Exit codes are 0, 1 (API), 2 (usage), 3 (authentication). The contract and its JSON Schemas are in CONTRACT.md.
Three ways to run it
A vendor CLI is built for one deployment: installed on a machine, logged in by the person at the keyboard, one process per command. Behind a gateway that fails. Every call spawns a process and logs in again, the acting user's identity cannot be forwarded, nothing declares what a command will do, and nothing is uniform to audit. aclif's command classes run unchanged in three places, and whoever runs them decides who supplies credentials, enforces policy, and keeps the audit trail.
- Run by the agent. The agent process spawns the binary, executes the command, and reads the JSON it returns. Credentials come from flags, environment variables, or a profile in the agent's own environment. Use this when one agent, one operator, and one set of credentials share a trust boundary.
- Run by a host application, the design-time case. An application sits between the model and aclif and holds the credentials. The model calls a tool the application defines, and the application executes the command, in-process or by passing a command string to the CLI. A person or an authoring tool uses this to let a model discover providers, introspect commands, and validate the exact command it will write into an agent. Use this when the model must never hold credentials and tool definitions must stay out of its context.
- Run by a gateway, the runtime case. A deployed agent submits commands, and one long-lived process serves many such agents. The gateway resolves credentials from the enterprise vault per request, checks policy against the acting user, records every call, and keeps connections warm. The agents hold no provider credentials and cannot widen their own scope. Use this when many agents share providers and one place must hold policy and audit.
| Run by the agent| Run by a host application| Run by a gateway
---|---|---|---
Credentials| flags, env, config.yaml| host-supplied resolver| vault-backed resolver, per request
Policy| config.yaml| capabilityGate hook| capabilityGate plus the host's middleware
Identity| --identity-token or env| the acting user on the invocation| the acting user and SSO claims from the request
Audit| stderr line per run| reporter events| reporter events, recorded by the host
Connections| file session cache| runtime pool| runtime pool, keyed per instance and identity
Details on the Embedding page.
Gateway deployments
Long-lived, embeddable deployment enables a gateway topology where additional security policy can be applied. One process the enterprise operates executes every command for every agent, and the arrangement provides:
- Credentials in one place. Resolved inside the gateway, per request, from the enterprise's vault. Agents hold none.
- Enterprise-wide canonical names. Tenant catalogs and alias sets are held by the gateway, so every agent uses the same names for the same records across every provider and instance.
- Every call attributed to a person. The acting user's identity travels with each call into the policy check and the audit record, even through a shared service account.
- Policy enforced once. Every command declares what it will do, and the gateway checks that declaration before the command's code loads. Agents cannot widen their own scope.
- One audit trail. The same event for every command from every agent, naming the user, the command, and the outcome.
Install, or build your own
npm install -g @aclif/core
# Your org's My Domain URL, no trailing slash
export SF_INSTANCE_URL=https://example.my.salesforce.com
# A session token from the Salesforce CLI (sf org login web first if needed)
export SF_ACCESS_TOKEN=$(sf org auth show-access-token -o me@example.com --json | jq -r .result.accessToken)
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 3" --json
Without the Salesforce CLI, use an API user. Salesforce emails the security token when the password is set or reset:
export SF_INSTANCE_URL=https://example.my.salesforce.com SF_USERNAME=me@example.com SF_PASSWORD=... SF_SECURITY_TOKEN=...
aclif salesforce data query --query "SELECT Id, Name FROM Account LIMIT 3" --json
The aclif binary ships with every built-in provider and needs Node 22 or later. The binary you ship is yours: one scaffold command produces a CLI with its own name, its own config directory, its own environment variables, and only the providers it chose. See Getting started and Build a CLI.
Providers
Salesforce, ServiceNow, DocuSign, and Agentforce are native and are included in every release. Google Workspace (Gmail, Calendar) is contributed. A private tier holds providers a fork keeps to itself, under a path upstream never commits to. Writing a provider takes little effort: it is a direct translation of the platform's API specification onto the command surface, a coding agent does it from a sample prompt in the repository, and the conformance suite checks the result. See Providers.
aclif is MIT licensed. Contributions follow CONTRIBUTING.md; the guide for people and coding agents changing the framework is AGENTS.md.