Build and deploy AI agents in YAML. Two modes: workflow (DAG pipelines), agent (autonomous LLM loop).
Highly experimental.APIs, schemas, and CLI flags change without notice. Not for production.[Report issues].
** AI Appliances - Build & Deploy Autonomous AI Agents and Agencies in YAML** Free. PDF, EPUB, and web.
Hands-on guide covering deterministic pipelines, multi-agent orchestration, error handling, and vendor-agnostic deployment - the production challenges most AI frameworks leave to you.
curl -LsSf https://raw.githubusercontent.com/kdeps/kdeps/main/install.sh | sh
Or with Homebrew (macOS and Linux):
brew install kdeps/tap/kdeps
DAG-deterministic request/response pipelines. Each resource declares its dependencies via requires:
and runs in order. Supports API server, web server, file input, and bot input.
POST /summarize {"url": "..."}
|
v
+---------------------+
| fetch | httpClient -- fetches the URL
+---------------------+
|
v
+---------------------+
| respond | chat -- summarizes the fetched body
+---------------------+
|
v
apiResponse <- output('respond') becomes the HTTP response body
apiVersion: kdeps.io/v1
kind: Workflow
metadata:
name: summarizer
version: "1.0.0"
targetActionId: respond
settings:
apiServer:
portNum: 16395
routes:
- path: /summarize
methods: [POST]
agentSettings:
installOllama: true
actionId: fetch
httpClient:
method: GET
url: "{{ get('url') }}"
timeout: 10s
---
actionId: respond
requires: [fetch]
chat:
model: llama3.2:1b
prompt: "Summarize this page: {{ output('fetch').body }}"
apiResponse:
response: "{{ output('respond') }}"
kdeps run workflow.yaml # local, instant startup
kdeps run workflow.yaml --dev # hot reload
Resource types: chat
, httpClient
, python
, exec
, sql
, email
, scraper
, browser
, embedding
, searchLocal
, searchWeb
, agent
, component
Expressions: get('key')
reads request input, output('actionId')
reads a prior step's result, set('key', val)
stores state. All expressions are safe inside {{ }}
β Jinja2 control flow ({% if %}
, {% for %}
) is also supported.
Autonomous LLM loop. Every resource in the workflow is auto-registered as a callable tool -- the LLM decides which tools to call, in what order, to complete the task.
stdin prompt
|
v
+---------------------+
| LLM | plans steps, picks tools
+---------------------+
|
+-- call tool: httpClient --> fetch URL
|
+-- call tool: python --> process data
|
+-- call tool: sql --> query database
|
v
+---------------------+
| LLM (again) | synthesizes results into final answer
+---------------------+
|
v
stdout response
kdeps serve workflow.yaml
kdeps serve workflow.yaml --model llama3.2 --system "You are a DevOps assistant."
The agent reads from stdin and runs until you exit. All resource types (http, python, exec, sql, ...) are available as tools without any extra wiring.
KDEPS_AGENT_MODEL=claude-3-5-sonnet # override model via env
KDEPS_AGENT_BACKEND=anthropic
An agency is a collection of agents that work together. Each agent is its own workflow.yaml
with its own resources, model, and logic. You wire them together using the agent:
resource type, which runs another agent's full workflow and returns its output β like calling a function, but the function is an entire AI pipeline.
POST /run-marketing-pipeline
β
βΌ
βββββββββββββββββββββββ
β content-writer β β its own workflow.yaml, writes the blog post
ββββββββββ¬βββββββββββββ
β output passed as params
βΌ
βββββββββββββββββββββββ
β cms-publisher β β its own workflow.yaml, publishes to CMS
βββββββββββββββββββββββ
β
βΌ
response
The orchestrating workflow calls each agent in order using agent:
:
actionId: draft
agent:
name: content-writer # runs agents/content-writer/workflow.yaml
params:
topic: "{{ get('topic') }}" # passed as get('topic') inside that agent
---
actionId: publish
requires: [draft]
agent:
name: cms-publisher # runs agents/cms-publisher/workflow.yaml
params:
content: "{{ output('draft') }}" # previous agent's output forwarded
apiResponse:
response: "{{ output('publish') }}"
Run an agency:
kdeps run agency.yaml
kdeps bundle build # Docker image
kdeps bundle export iso # bootable edge ISO
kdeps bundle prepackage # self-contained binary per arch
kdeps export k8s # Kubernetes manifests
kdeps registry search <query>
kdeps registry install <package>
kdeps registry submit --tag v1.0.0 # generate formula for kdeps.io PR
A coding-agent skill teaches Claude Code, Cursor,
Grok, and other agents how to scaffold kdeps workflows, components, and agencies β
including kdeps.pkg.yaml
for kdeps.io distribution.
git clone https://github.com/kdeps/skill ~/.claude/skills/kdeps
Docs: kdeps.com/getting-started/agent-skills
kdeps edit # opens ~/.kdeps/config.yaml
kdeps doctor # check config, Ollama, Python, installed agents
llm:
backend: ollama # ollama, openai, anthropic, groq, ...
openai_api_key: sk-... # only needed for the relevant backend
defaults:
timezone: UTC
python_version: "3.12"
resource_defaults: # applied to every resource of that type
chat:
timeout: 60s # hard stop per LLM call
context_length: 4096
http:
timeout: 30s
Per-agent config overrides: add an agents:
block keyed by the workflow name to override globals for that agent only:
agents:
my-agent: # matches metadata.name in workflow.yaml
llm:
backend: openai
openai_api_key: sk-...
Config is validated on load. Warnings go to stderr for unknown keys, missing API keys, invalid durations, and agent profiles that don't match any installed workflow.
When apiServer
is configured, authentication is required. Set the token via KDEPS_API_AUTH_TOKEN
or api_auth_token
in ~/.kdeps/config.yaml
(never in workflow.yaml
). Clients send Authorization: Bearer <token>
or X-Api-Key: <token>
. /health
is exempt. /_kdeps/*
management routes use KDEPS_MANAGEMENT_TOKEN
.
export KDEPS_API_AUTH_TOKEN=your-secret-token
kdeps run workflow.yaml
settings:
apiServer:
rateLimit:
requestsPerMinute: 60 # sustained per-IP rate; excess gets 429
burst: 10 # burst allowance above the sustained rate
maxBodyBytes: 1048576 # 1 MB request body cap; 413 if exceeded
trustedProxies: # honor X-Forwarded-For only from these peers
- "10.0.0.0/8"
cors:
allowOrigins:
- https://myapp.com
webServer: # optional; same rateLimit/maxBodyBytes/maxConcurrent fields
rateLimit:
requestsPerMinute: 120
certFile: /path/to/cert.pem # TLS -- omit for plain HTTP
keyFile: /path/to/key.pem
Structured JSON via log/slog
. Set KDEPS_LOG_FORMAT=json
for production output. Default level: WARN. Flags: --verbose
(INFO), --debug
(DEBUG).
Documentation | Registry | Apache 2.0