DeclarAgent
Declarative runbook executor for AI agents. Validate, dry-run, and safely run real CLI workflows.
Install / Use
/learn @shiehn/DeclarAgentREADME
DeclarAgent

Declarative runbook executor for AI agents. Validate, dry-run, and safely execute multi-step YAML workflows from any LLM tool-use loop.
Why DeclarAgent?
LLM agents are great at reasoning but dangerous when executing. DeclarAgent gives agents a structured, auditable, and safe way to run real workflows:
- YAML plans — human-readable, version-controllable runbooks
- Three step types — shell commands (
run), built-in actions (action), and HTTP requests (http) - Dry-run & explain — inspect exactly what will happen before it does
- Destructive-step gating — steps marked
destructive: truerequire explicit--approve - Structured JSON results — every run returns machine-readable output with typed errors
- Built-in actions — file I/O, JSON manipulation, and env access without shell gymnastics
- Template engine — reference outputs from prior steps with
${{steps.<id>.outputs.<key>}} - MCP server — expose plans as directly callable tools over the Model Context Protocol
- Plan-as-tool — drop YAML files in a directory, each becomes an MCP tool automatically
Installation
Requires Go. This project is currently only tested on macOS.
go install github.com/shiehn/declaragent@latest
# Verify
declaragent --help
Platform note: Linux should work out of the box (the codebase uses
sh -cwith no OS-specific code). Windows requires WSL or a similar POSIX-compatible shell.
Quick Start
# Validate a plan
declaragent validate plan.yaml
# See what it would do
declaragent explain plan.yaml --input branch=main
# Dry-run (resolves templates, shows commands)
declaragent dry-run plan.yaml --input branch=main
# Execute for real
declaragent run plan.yaml --input branch=main
# Execute with destructive steps allowed
declaragent run plan.yaml --input branch=main --approve
# Start MCP server with a plans directory
declaragent mcp --plans ./plans
Plan Schema

Plans are YAML files with a simple structure. Each step does exactly one thing: run a shell command, call a built-in action, or send an HTTP request.
name: deploy-service
description: Build, test, and deploy the service
inputs:
env:
required: true
description: Target environment
tag:
default: latest
steps:
- id: test
run: go test ./...
outputs:
result: stdout
- id: build
run: docker build -t myapp:${{inputs.tag}} .
- id: check_health
http:
url: "https://${{inputs.env}}.example.com/health"
method: GET
outputs:
status: stdout
- id: deploy
run: kubectl apply -f k8s/${{inputs.env}}.yaml
destructive: true
Step Types
| Type | Field | Description |
|------|-------|-------------|
| Shell | run | Runs a shell command via sh -c. Captures stdout/stderr. |
| Action | action | Calls a built-in action (file I/O, JSON, env). |
| HTTP | http | Sends an HTTP request. Response body captured as stdout. |
Each step must have exactly one of run, action, or http.
HTTP Step Fields
- id: call_api
http:
url: "https://api.example.com/data" # required
method: POST # default: GET
headers:
Authorization: "Bearer ${{inputs.token}}"
body: '{"key": "value"}' # template-resolved string
outputs:
response: stdout # response body
Key Fields
| Field | Description |
|-------|-------------|
| name | Plan identifier |
| inputs | Named parameters with required, description, and default |
| steps[].id | Unique step identifier |
| steps[].run | Shell command to execute |
| steps[].action | Built-in action (alternative to run) |
| steps[].http | HTTP request (alternative to run and action) |
| steps[].with | Parameters passed to built-in actions |
| steps[].outputs | Capture step output (e.g., stdout) |
| steps[].destructive | If true, blocked unless --approve is passed |
CLI Commands
| Command | Description |
|---------|-------------|
| validate <plan.yaml> | Check plan structure and references |
| explain <plan.yaml> | Show resolved steps without executing |
| dry-run <plan.yaml> | Simulate execution, resolve templates |
| run <plan.yaml> | Execute the plan |
| mcp [--plans DIR] | Start MCP stdio server |
| skill [--plans DIR] | Generate a Claude Code Skill (SKILL.md) |
All commands accept --json for machine-readable output and --input key=value for plan inputs.
Built-in Actions
| Action | Params | Description |
|--------|--------|-------------|
| file.write | path, content | Write content to a file |
| file.append | path, content | Append content to a file |
| json.get | file, path | Read a value from a JSON file |
| json.set | file, path, value | Set a value in a JSON file |
| env.get | name | Read an environment variable |
Structured Results

Every execution returns a JSON result:
{
"run_id": "a1b2c3",
"success": true,
"steps": [
{"id": "test", "status": "success", "exit_code": 0, "duration": "1.2s"}
],
"outputs": {"test.result": "ok"},
"artifacts": [".declaragent/a1b2c3/test/stdout"],
"errors": []
}
Errors are typed for agent decision-making:
| Error Type | Retryable | Meaning |
|-----------|-----------|---------|
| VALIDATION_ERROR | No | Bad plan or missing inputs |
| STEP_FAILED | No | A command returned non-zero |
| PERMISSION_DENIED | No | Destructive step without --approve |
| SIDE_EFFECT_BLOCKED | No | Destructive step blocked in dry-run |
| TRANSIENT | Yes | Temporary failure, safe to retry |
| TIMEOUT | Yes | Step exceeded time limit |
| TOOL_NOT_FOUND | No | Unknown action referenced in step |
| PRECONDITION_FAILED | No | Step precondition not met |
| CANCELLED | No | Execution was cancelled |
MCP Integration

Run declaragent mcp to start a Model Context Protocol stdio server.
Plan-as-Tool
When you pass --plans <directory>, every YAML plan in that directory becomes a directly callable MCP tool:
declaragent mcp --plans ./plans
- Tool
name= planname - Tool
description= plandescription - Tool
inputSchema= derived from planinputs - Calling the tool = executing the plan with the provided inputs
This means an LLM agent can discover and invoke your plans without knowing anything about DeclarAgent's internal plan format.
Integrations
Claude Code
Add to .claude/settings.json:
{
"mcpServers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
Claude Desktop
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
Cursor
Add to .cursor/mcp.json in your project root:
{
"mcpServers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
GitHub Copilot (VS Code)
Add to .vscode/mcp.json in your project root. Note: Copilot uses "servers" instead of "mcpServers":
{
"servers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
Amazon Q Developer
Add to ~/.aws/amazonq/mcp.json:
{
"mcpServers": {
"declaragent": {
"command": "/path/to/declaragent",
"args": ["mcp", "--plans", "/path/to/your/plans"]
}
}
}
ChatGPT
ChatGPT requires a remotely accessible SSE endpoint. See SSE Transport below, then add the public URL in ChatGPT's MCP settings.
SSE Transport
For remote hosting or HTTP-based clients (e.g., ChatGPT), start the MCP server with SSE transport:
declaragent mcp --transport sse --port 19100 --plans ./plans
The server will be available at http://localhost:19100/sse. Expose this URL publicly (e.g., via a reverse proxy or tunnel) for clients that require a remote endpoint.
Built-in MCP Tools
These meta-tools are always available regardless of --plans:
| Tool | Description |
|------|-------------|
| plan.validate | Validate a plan YAML file |
| plan.explain | Explain a plan without executing |
| plan.dry_run | Dry-run a plan |
| plan.run | Execute a plan |
| plan.schema | Return the plan YAML schema |
Claude Code Skills
As an alternative to MCP, you can generate a Claude Code Skill that teaches Claude Code how to use the DeclarAgent CLI directly. Skills are simpler and more token-efficient than MCP since they work through the CLI rather than a server.
# Generate a skill with a plan catalog
declaragent skill --plans ./plans
# Custom output directory and binary name
declaragent skill --plans ./plans --output .claude/skills/declaragent --binary declaragent
This creates .claude/skills/declaragent/SKILL.md containing CLI usage instructions and a catalog of your available plans. Claude Code automatically discovers skills in .claude/skills/, so once generated, any user (or agent) can invoke it via /declaragent.
| Flag | Default | Description
