A lightweight, configurable agentic runtime that turns any LLM into a tool-using, A2A-compatible agent. Deploy with a system prompt, agent card, and tool config — no code changes needed. Runs at ~10 MiB per pod on OpenShift.
make build
ANTHROPIC_API_KEY=sk-... ./bin/docsclaw serve \
--config-dir testdata/standalone \
--listen-plain-httpInstall the A2A CLI to discover and interact with agents:
go install github.com/a2aproject/a2a-go/v2/cmd/a2a@latest
a2a discover http://localhost:8000
a2a send http://localhost:8000 "Summarize https://go.dev/blog/go1.24"Or use the built-in interactive chat:
./bin/docsclaw chat --agent-url http://localhost:8000The agent uses web_fetch to retrieve the page, then summarizes
it. Replace the text with any task — the agent decides which tools
to call.
DocsClaw reads its personality from a config directory:
my-agent/
├── system-prompt.txt # Who the agent is
├── agent-card.json # A2A metadata (name, skills, URL)
├── agent-config.yaml # Which tools to allow, loop settings
└── skills/ # Optional SKILL.md instructions
└── url-summary/
└── SKILL.md
Same binary, different config = different agent.
Without agent-config.yaml, DocsClaw runs in single-shot mode
(no tools, prompt-in/response-out). With it, the agentic loop
is enabled and the LLM can call tools iteratively until the task
is complete.
make image-push
oc new-project docsclaw
oc create secret generic llm-secret --from-literal=LLM_API_KEY=sk-...
oc apply -f deploy/standalone-agent.yamlThe manifest bundles ConfigMap + Deployment + Service + Route in
a single file. Secret examples for Anthropic, OpenAI, and MaaS
are in deploy/. Test via the Route:
curl -X POST https://$(oc get route docsclaw -o jsonpath='{.spec.host}')/a2a \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"message/send","id":"1",
"params":{"message":{"messageId":"m1","role":"user",
"parts":[{"kind":"text","text":"Run uname -a and describe this system"}]}}}'Skills are markdown files that teach the agent specialized
behaviors. The agent discovers them at startup and can load them
on demand via the load_skill tool.
To add a skill, create a directory under skills/ with a
SKILL.md file:
---
name: my-skill
description: What this skill does (shown to the LLM at startup)
---
# My skill
Step-by-step instructions for the LLM to follow...See testdata/standalone/skills/ for examples (url-summary,
code-review).
Discovered skills are automatically added to the AgentCard served
at /.well-known/agent-card.json. If a skill includes a
skill.yaml with richer metadata (namespace, author, tools), the
AgentCard entry gets derived tags. Static skills in
agent-card.json take precedence on ID conflict.
Skills can be packaged as OCI artifacts and distributed via registries (quay.io, GHCR, Harbor, Zot) using the skillctl CLI. On OpenShift 4.20+ they mount directly as image volumes — no init container needed.
skillctl pack examples/skills/resume-screener
skillctl push --as-image examples/skills/resume-screener \
quay.io/myorg/skill-resume-screener:1.0.0
skillctl inspect quay.io/myorg/skill-resume-screener:1.0.0See the OCI skills guide for the full workflow including signing, verification, and deployment manifests.
The agent's personality. Plain text, no special format.
A2A protocol metadata — name, description, capabilities. Discovered skills are merged into the card at startup; you only need to hardcode skills here if you want static entries that override discovery. See the A2A spec for the full schema.
Controls which tools are available and loop behavior:
tools:
allowed: # Only these tools are available to the LLM
- exec
- web_fetch
- read_file
- write_file
exec:
timeout: 30 # Max seconds per command
max_output: 50000 # Truncate output after this many chars
web_fetch:
allowed_hosts: # SSRF protection (empty = all allowed)
- go.dev
- kubernetes.io
workspace: /tmp/agent-workspace # read_file/write_file root
loop:
max_iterations: 10 # Max tool-use rounds before giving up| Tool | Description |
|---|---|
exec |
Run shell commands (dangerous commands blocked) |
web_fetch |
HTTP GET with SSRF protection |
read_file |
Read files (workspace-restricted) |
write_file |
Write files (workspace-restricted) |
rag_search |
Semantic search over a vector database (see below) |
load_skill |
Load a SKILL.md (always available when skills exist) |
Add an optional rag: block to agent-config.yaml to let the
agent retrieve context from a vector database before answering:
rag:
backend: weaviate
url: http://weaviate:8080
collection: DocsThe rag_search tool auto-registers when rag: is present (no
tools.allowed entry needed). Uses raw HTTP/GraphQL — zero new
dependencies. The rag.Client interface supports adding more
backends (Milvus, pgvector) as drop-in connectors. See
testdata/rag/README.md for local
testing with Weaviate and Ollama.
Set via environment variables:
| Variable | Description |
|---|---|
LLM_API_KEY or ANTHROPIC_API_KEY |
API key |
LLM_PROVIDER |
anthropic (default), openai, litellm |
LLM_MODEL |
Model name (default: claude-sonnet-4-6) |
LLM_BASE_URL |
Base URL for OpenAI-compatible APIs |
┌─────────────────────────────────────────────────┐
│ docsclaw serve │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────┐ │
│ │ A2A │──▶│ Agentic │──▶│ LLM │ │
│ │ Endpoint │ │ Loop │ │ Provider │ │
│ └──────────┘ └────┬─────┘ └────────────┘ │
│ │ │
│ ┌─────────┼─────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ exec │ │ web │ │ read │ ... │
│ │ │ │ fetch │ │ file │ │
│ └────────┘ └────────┘ └────────┘ │
│ │
│ Config: system-prompt.txt + agent-config.yaml │
└─────────────────────────────────────────────────┘
make build # Build binary to bin/docsclaw
make test # Run tests
make lint # Run golangci-lint
make image # Build container image (local dev)
make image-push # Build and push to GHCROverride defaults:
make image REGISTRY=my-registry.io/docsclaw DEV_TAG=v1.0
make image CONTAINER_ENGINE=dockerReleases are automated via GoReleaser. Tag a commit and push to trigger the workflow:
git tag v0.1.0
git push --tagsThis produces:
- Binaries for linux/darwin/windows (amd64, arm64)
- Multi-arch container images on
ghcr.io/redhat-et/docsclaw - Homebrew formula (
brew install pavelanni/tap/docsclaw) - SHA256 checksums
Apache License 2.0