Agent tool calling has a context problem. Every SaaS API brings its own schema, error vocabulary, and authentication flow. MCP servers solve this by publishing a fixed tool list, but that trades coverage for token cost. Publish every operation and you burn context on hundreds of definitions per turn. Publish a handful of broad operations and you leave most of the API unreachable.
Aclif takes a different approach: one canonical CLI grammar across all SaaS providers, with lazy schema loading that pulls command definitions only when the agent asks for them. The entire API surface stays reachable without standing context cost.
How It Works
Aclif sits between the agent and SaaS APIs as a command-line framework. The agent issues commands in a single grammar, and Aclif translates them into provider-specific API calls.
Core mechanics:
- Lazy schema loading: Command definitions load on demand when the agent runs
aclif learn <provider>, not at initialization. - Canonical naming: The same record has the same name across platforms.
data queryworks identically on Salesforce and ServiceNow. - Single error envelope: One JSON error structure across all providers, so the agent doesn’t need provider-specific error handling.
- Design-time vs. runtime separation: Workflows can embed exact command strings at design time, then execute them at runtime with credentials supplied by the execution context.
# Agent learns a command schema on demand
aclif learn salesforce --json
aclif salesforce data query --schema
# Same grammar, different provider
aclif servicenow data query --table incident --query "active=true^priority=1" --dry-run
aclif salesforce data query --query "SELECT Id FROM Account LIMIT 3" --dry-run
The framework exposes metadata alongside commands: schema, examples, and safety flags. An agent can inspect before execution.
Architecture: Command Normalization Layer
Aclif normalizes heterogeneous SaaS APIs into a single command structure. The translation happens in three stages:
- Command parsing: Aclif parses the canonical command syntax into an internal representation.
- Provider mapping: The framework maps canonical parameters to provider-specific API fields.
- Execution and envelope: The API call executes, and the response wraps in a standard JSON envelope.
Authentication and session management:
- Credentials are supplied at runtime by the execution context, not embedded in the command.
- Each provider plugin handles its own auth flow (OAuth, API keys, session tokens).
- The agent never holds both the command definition and the credential.
Rate limiting and error propagation:
- Provider-specific rate limits surface through the unified error envelope.
- Errors include a canonical code, a provider-specific message, and retry metadata.
- The agent sees the same error structure whether it hits a Salesforce governor limit or a ServiceNow throttle.
Deployment Model
Aclif runs as a local CLI binary installed via npm. It’s not a hosted gateway or a proxy server. The agent shells out to the aclif binary, which makes direct API calls to SaaS providers.
Implications for orchestration:
- No network hop: The agent and Aclif run in the same execution context. No additional latency from a gateway.
- Credential isolation: The orchestration layer supplies credentials via environment variables or config files at runtime.
- Stateless execution: Each command is independent. No session state persists between calls unless the provider requires it.
This model works for single-agent workflows and local automation. It doesn’t fit multi-tenant hosted agent platforms without wrapping Aclif in a service layer.
Trade-offs: Coverage vs. Abstraction Leakage
| Dimension | Aclif Approach | MCP Fixed Tool List |
|---|---|---|
| Context cost | Zero standing cost, pay per command learned | Full tool list loaded every turn |
| API coverage | Entire API reachable via lazy loading | Limited to published tools |
| Error handling | Unified envelope, provider details in metadata | Provider-specific error schemas |
| Abstraction leakage | Provider quirks surface in query syntax | Abstraction hides provider differences |
| Agent complexity | Agent learns one grammar, many providers | Agent learns one tool set per server |
The canonical grammar doesn’t eliminate provider differences. Salesforce uses SOQL, ServiceNow uses query strings. The agent still needs to know which query language to use, but it doesn’t need to learn separate error handling or authentication flows.
Failure Modes
Schema drift:
- SaaS providers change APIs without notice. Aclif’s provider plugins need updates to track schema changes.
- Mitigation: The
--schemaflag lets the agent inspect the current definition before execution.
Authentication expiry:
- OAuth tokens expire mid-workflow. The agent sees a 401 in the unified error envelope but has no built-in refresh logic.
- Mitigation: The orchestration layer must handle token refresh and retry.
Provider-specific limits:
- Salesforce governor limits, ServiceNow ACLs, and rate limits all surface as errors, but the agent can’t predict them without provider-specific knowledge.
- Mitigation: The error envelope includes retry metadata, but the agent needs logic to interpret it.
Command ambiguity:
- Canonical names work until two providers expose fundamentally different operations under the same name.
- Mitigation: Aclif namespaces commands by provider (
aclif salesforce data queryvs.aclif servicenow data query), but the agent must choose the right provider.
Code Example: Embedding a Command in a Workflow
Aclif separates command definition from execution. A workflow can embed an exact command string at design time, then execute it at runtime with credentials supplied by the execution context.
// Design time: author defines the command
const workflowStep = {
command: "aclif salesforce data query --query 'SELECT Id, Name FROM Account WHERE Industry = \"Technology\" LIMIT 10'",
credential: "runtime-supplied"
};
// Runtime: orchestrator executes with credentials
const { execSync } = require('child_process');
function executeStep(step, credentials) {
const env = {
...process.env,
SALESFORCE_TOKEN: credentials.salesforce.token,
SALESFORCE_INSTANCE: credentials.salesforce.instance
};
try {
const result = execSync(step.command, { env, encoding: 'utf8' });
return JSON.parse(result);
} catch (error) {
// Unified error envelope
const errorData = JSON.parse(error.stderr);
if (errorData.retryable) {
// Handle retry logic
}
throw error;
}
}
The workflow author never sees the credential. The runtime executor never defines the command. This separation matters for security boundaries in multi-tenant systems.
When to Use Aclif
Good fit:
- Single-agent workflows that span multiple SaaS platforms.
- Local automation where the agent and CLI run in the same execution context.
- Scenarios where you need the entire API surface reachable without burning context on unused tools.
- Workflows where you can separate command definition (design time) from credential supply (runtime).
Poor fit:
- Multi-tenant hosted agent platforms without a service wrapper around the CLI.
- Scenarios where you need sub-100ms tool call latency (shelling out to a CLI adds overhead).
- Agents that need to discover tools dynamically without any schema inspection step.
- Workflows where provider-specific optimizations (batching, caching, connection pooling) matter more than interface consistency.
Technical Verdict
Aclif solves the context cost problem for multi-platform agents by deferring schema loading until the agent asks for it. The canonical grammar reduces the learning surface, but it doesn’t eliminate provider-specific quirks. You still need to know SOQL vs. ServiceNow query strings.
The local CLI deployment model keeps latency low and credential handling simple, but it doesn’t fit hosted multi-tenant platforms without additional infrastructure. If you’re building a single-agent workflow that needs to reach across Salesforce, ServiceNow, and other SaaS APIs without burning context on hundreds of tool definitions, Aclif gives you a clean abstraction. If you need a hosted gateway with connection pooling and multi-tenant isolation, you’ll need to wrap it in a service layer.
The design-time vs. runtime separation is the most interesting piece. Embedding exact command strings in workflows while deferring credential supply creates a clear security boundary. That pattern works well for automation platforms where workflow authors and runtime executors are different roles.