Guide
A custom agent extends cliq’s built-in catalog with your own logic. Agents are Node.js programs that receive an invoke payload from the daemon and return output. The SDK handles the protocol; you implement one method.
How agents work
When a phase fires, cliqd:- Resolves the agent name from the agents path (filesystem lookup)
- Spawns the agent’s entry point as a child process
- Pipes the invoke payload (JSON) to stdin
- The agent posts events and a terminator (
complete/error) back to cliqd over HTTP
1. Set up the SDK
@getcliqio/cliq-sdk.
2. Write the manifest
Every agent needs amanifest.json in its directory. The daemon validates every field on load — invalid manifests are skipped with a warning.
Top-level fields
Minimal example:
Agent types
Inputs
Theinputs block declares what the agent accepts. Each key is the input name; the value is a field descriptor.
Validation rules: Each input must be an object with type (valid type string) and required (boolean). required_unless must be an array when present. enum must be an array when present.
Type reference
required_unless — conditional requirements
Use when two fields are mutually exclusive (at least one must be present):
sources or target_entries (or both).
source: "runtime" — run-time inputs
Inputs with source: "runtime" are not set in the team YAML — they come from the user at run time via cliq run -i:
Subfields
When an input hastype: "object", you can document its internal structure with fields. This is used for validation and documentation — the daemon passes the object through to the agent:
hug agent’s review input — team authors see exactly what fields the object expects.
Full LLM agent inputs example
From the built-incursor agent:
Settings
Thesettings block declares daemon settings the agent reads from ctx.settings. Users configure them with cliq settings set agents.<name>.<key> <value>.
settings must be an object. settings.required must be an array. settings.optional must be an array when present. Each entry must be a plain string or an object with a non-empty key string.
Entry formats
Entries inrequired and optional accept two forms:
Plain string — just the key name:
Object entry fields
when — conditional settings
The when field gates a setting on another setting’s value. Each key in when is a peer setting name; the value is the required match:
git agent: github.token is only required when provider is "github". When provider is "bitbucket", the GitHub settings are ignored and the Bitbucket ones are required instead.
Validation: when must be an object with string values. Each value must be a string.
Output
Theoutput block describes the shape of data the agent returns via ctx.complete():
The
data field is documentation — it describes what keys appear in the data array that on_invoke returns. The daemon does not validate output shape at runtime.
Binaries
List system binaries the agent needs on$PATH:
cliq doctor checks each binary with command -v. Agents that are pure Node.js / HTTP can omit this.
Env
Host environment variables the agent needs inherited from the OS:Actions (connector agents)
Connector agents can document their per-action API with anactions block. This is not validated by the SDK but powers the OpenAPI docs generated for the Agents tab:
MCP (LLM agents only)
Themcp block declares MCP (Model Context Protocol) server support. Users configure servers in the agent’s settings (agents.<name>.mcp.servers).
mcp.transports must be a non-empty array of "http" and/or "stdio". mcp.allow_custom must be a boolean when present. mcp.presets must be an array when present. Preset names must be 1–64 characters ([A-Za-z0-9_-]), no duplicates.
Preset format
Each preset is a server the user can enable with one click in the Hub UI:
Secret format: Each secret has
key (required, UPPER_SNAKE_CASE), optional description, optional help_url. Users set secrets with cliq settings set agents.<name>.mcp.secrets.<KEY> <value>.
stdio example (Notion):
3. Write the handler
Extend one of the SDK base classes and implementon_invoke:
The context object
Every agent gets a context (ctx) with these fields and methods:
Data fields:
Methods:
Returning vs calling
ctx.complete: If on_invoke returns an AgentOutput, the SDK auto-sends it as complete. You can also call ctx.complete() explicitly and return void.
Class hierarchy
Pick the base class that matches your agent type:StandardAgent— most custom agents start here. Gets upstream data and commands.ConnectorAgent— for agents that talk to external APIs. Getsaction,sources,targets, andcredentials.GateAgent— for custom gate logic. Getscheck_resultsand verdict methods (pass,route,escalate).
4. Add to the agents path
Create anagents.json in your agents directory:
~/.cliqrc/agents (built-ins) is always appended last. No restart needed — agent resolution is JIT (reads from disk on every phase start).
Verify:
Directory layout
agents.json. The optional path field in an entry supports absolute or relative paths:
Shadowing built-ins
To override a built-in agent, place an agent with the same name in a directory that precedes the system dir. The first match on the path wins. cliqd logs when an agent is shadowed.5. Use in a team
Reference your agent by name inteam.yml:
my-agent from the agents path when the phase fires.
6. Register on Hub (optional)
Registration pushes your agent’s manifest metadata to Hub so it appears in the catalog. The code stays on your machine.- Other users in your org want to see the agent in the Hub UI
- You publish a team that references the agent (Hub dispatch validates that referenced agents are registered)
What registration does NOT do
- It does not upload your code — Hub stores manifest metadata only
- It does not install the agent on other machines — teammates add it to their own agents path
- It does not make the agent available for download — there is no agent distribution system
Example: a complete exec agent
manifest.json:
index.js:
Validation and debugging
~/.cliqrc/logs/runs/<daemon_id>/<run_id>.log.
Related
- Agent catalog and built-ins → Agents
- SDK package →
@getcliqio/cliq-sdk - CLI agent commands → CLI — Agents
- Local development → Local Development