dograh-ctl
A CLI to run a self-hosted Dograh voice-agent platform from the terminal: agents, calls, transcripts, numbers, models, campaigns, tools, keys, and an MCP server that exposes all of it to an agent. No dashboard clicking.
Why this exists
Dograh ships a REST API, generated SDKs, a dashboard, and an MCP server for building agents. It does not ship a command line for running them. Everything you do to operate a voice agent in production (which number routes where, what the last call cost, flip a model, place a test call, read the transcript) means clicking through the UI. dograh-ctl is the missing operations surface: scriptable (--json everywhere), diffable, and automatable, and dograh-ctl serve hands the same verbs to an agent over MCP.
Install
From PyPI:
uv tool install dograh-ctl # or: pip install dograh-ctl
uvx dograh-ctl --help # try it without installing
Or straight from GitHub:
uv tool install git+https://github.com/erickcxc/dograh-ctl
From a clone: pip install -e . (or uv sync). Python 3.10+.
Point it at your instance and key (create a key in Dograh, under Developers):
export DOGRAH_BASE_URL=https://your-dograh-host
export DOGRAH_API_KEY=dgr_xxx
dograh-ctl ping
Auth is the X-API-Key header. The key is read from the environment and stays in .env (gitignored), never in the repo, never in this tool's output.
Quick start
dograh-ctl agents list # what agents exist
dograh-ctl agents get 7 # graph summary + model override (masked)
dograh-ctl runs chat 7 -m "hello" # talk to an agent, no telephony
dograh-ctl models set --realtime google_realtime/gemini-3.1-flash-live-preview
dograh-ctl agents publish 7 # edits are drafts until published
dograh-ctl runs trigger 7 --to +13135550100 --yes # place a real call
dograh-ctl runs transcript 501 # read it back
dograh-ctl runs latency --json | jq .p95 # everything is scriptable
Commands
Every command accepts --json (raw API payload, for scripts). Every failure is one line on stderr with an exit code: 2 for local configuration problems, 1 for anything the instance refused or could not be reached for. No tracebacks.
| Group | Command | What it does |
|---|---|---|
ping |
Verify connectivity and API-key auth. | |
| agents | list |
List voice agents (workflows). |
get <id> |
Name, status, version, node summary, model override (secrets masked). | |
create -u USE_CASE -d DESCRIPTION [--call-type] |
Generate an agent from a use case. | |
set-prompt <id> PROMPT |
Replace the prompt on every agentNode (saves a draft). | |
rename <id> NAME |
Rename. | |
set-model <id> --realtime P/M / --llm P/M |
Per-agent model override, read-modify-write (saves a draft). | |
publish <id> |
Promote the draft. Production inbound calls use the published version. | |
validate <id> |
Validate the draft graph. | |
| runs | list [-n 100] |
Recent call runs: duration, disposition, model. |
latency [-n 100] |
avg/p50/p95/min/max call duration. | |
trigger <agent> --to +E164 [--config ID] [--from-id ID] --yes |
Place an outbound call; resolves the run id. | |
transcript <run> [--agent ID] |
Print the transcript. | |
recording <run> [--out FILE] [--track ...] |
Download the recording. | |
chat <agent> [-m TEXT] |
Text session with an agent (no telephony). | |
| numbers | list |
Numbers and which agent each routes to. |
assign +E164 <agent> |
Route a number to an agent. | |
add +E164 [--agent ID] [--label] [--config ID] |
Register a number you already own. | |
remove +E164 --yes |
Remove from Dograh (does not release it at the carrier). | |
| models | show |
Org model configuration: mode, realtime, llm, tts, stt. |
set --realtime P/M / --llm P/M / --tts P/M / --stt P/M |
Change one block; the server re-merges your stored secrets. | |
| campaigns | list, status <id>, watch <id> [--interval] [--once] |
Campaigns, live progress, and a live dashboard while a campaign dials (numbers masked to the last 4 digits). |
create --name N --agent ID --csv FILE [--config ID] [--max-concurrency N] |
Upload a CSV (phone_number column, see examples/campaign-sample.csv) and create. |
|
start <id> --yes, pause <id> |
Control. start places real calls. |
|
| telephony | configs, providers |
Telephony configurations; supported providers and their fields. |
| tools | list [--status] [--category] |
Tools agents can call (HTTP, MCP, transfer, ...). |
| keys | list [--all], create NAME [--reveal], revoke <id> --yes |
Org API keys. create prints the prefix only unless --reveal. |
| serve | serve |
MCP server (stdio) exposing the operations verbs above. |
Buying a number is a carrier action: twilio phone-numbers:buy:local --country-code US --area-code 313, then dograh-ctl numbers add +1313... --agent 7.
Safety rails
- Verbs that place calls or cost money (
runs trigger,campaigns start,numbers remove,keys revoke) ask for confirmation; pass--yesin scripts. models setandagents set-modelread the current configuration, change one block, and write the whole thing back, so masked secrets are merged by the server, never overwritten with a placeholder.- Nothing prints a secret.
keys createshows the prefix;--revealprints the full key once. - Edits to an agent are drafts.
agents publishis the step that changes production behaviour.
For AI agents (Claude Code and any MCP client)
This is the reason dograh-ctl exists: a coding agent should be able to create a voice agent, publish it, give it a number, test it, call it, and read the transcript, without a human clicking through a dashboard.
- One-step install for Claude Code (MCP server + skill + setup command):
claude plugin marketplace add erickcxc/dograh-ctl claude plugin install dograh-ctl
The plugin registersdograh-ops(uvx dograh-ctl serve, credentials passed through from your shell as${DOGRAH_BASE_URL}/${DOGRAH_API_KEY}, never stored) and installs thedograh-ctlskill, which teaches the lifecycle: create -> set_prompt -> set_model -> validate -> publish -> number -> chat test -> call -> transcript./dograh-ctl-setupchecks the environment and the connection. - Any MCP client:
dograh-ctl mcp-configprints theclaude mcp addline and the JSON block. - Shell-driving agents: every command takes
--json; exit codes are stable (2 config, 1 remote);AGENTS.mdhas the conventions. - Safety for autonomous use: tools that place calls (
runs_trigger,campaigns_start) are annotated destructive so clients confirm; writes are idempotent read-modify-write; payloads are scrubbed of keys;keys create/revokeandnumbers removeare CLI-only on purpose.
Build with Dograh's MCP, operate with dograh-ctl serve
Dograh mounts its own MCP server at {DOGRAH_BASE_URL}/api/v1/mcp (Streamable HTTP, same API key). Its tools are for authoring: create and save workflows, list node types, search the docs, pull the voice-prompting guide.
dograh-ctl serve is the operations plane over stdio: list agents, place a call, read a transcript, latency stats, route numbers, flip models, watch a campaign. Point Claude Code (or any MCP client) at both and an agent can build a voice agent, call it, and read what happened.
{ "mcpServers": { "dograh-ops": { "command": "dograh-ctl", "args": ["serve"] } } }
Verification
Shapes are taken from the Dograh source at dograh-hq/dograh@b32187d8 (2026-08-20) and pinned in tests/fixtures. Ten endpoints are Dograh's stable SDK contract; the rest are dashboard-internal and may drift between Dograh releases, which is why every command is mocked-HTTP tested and the fixtures cite their schema.
| Status | Commands |
|---|---|
| Live-verified on a self-hosted instance | ping, agents list/get/create/set-prompt/rename/set-model/validate/publish, models show/set, runs list/latency/chat/transcript, numbers list/assign, telephony configs/providers, tools list, keys list, campaigns list, serve (stdio handshake + live tool call) |
| Verified against the upstream schemas with mocked HTTP | runs trigger/recording, numbers add/remove, keys create/revoke, campaigns create/start/pause/status |
Live-verified rows move as commands are exercised against a real instance; nothing is listed as live-verified unless it was.
Design
- Thin
httpxclient with theX-API-Keyheader;DOGRAH_BASE_URLandDOGRAH_API_KEYfrom the environment. typerandrich; one output module so tables and--jsonnever drift; one error path so no command shows a traceback.- Talks only to your own self-hosted Dograh. This is a control layer on top of Dograh; it never vendors or republishes Dograh's code.
- Tests:
uv run pytest(respx-mocked HTTP, fixtures mirror the upstream schemas). CI runs lint + tests on Python 3.10 and 3.12.
The command surface
The whole operations surface of a self-hosted Dograh instance, in one tool: 9 command groups, 32 commands, every one of them tested, and the same verbs exposed to agents through serve. Day 8 shipped the skeleton (ping, agents, runs, numbers); Day 9 completed the map and tagged v0.2.0.
Built live
Designed and built live on the AI by Erick stream (one-hour build challenge, Days 8 and 9), as the engine-first pivot into voice.
Daily builds: https://www.youtube.com/channel/UCWCXKXvNtNbKPkeK_t5CZlg
I build agentic systems like this for businesses. Reach me through the channel.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dograh_ctl-0.3.1.tar.gz.
File metadata
- Download URL: dograh_ctl-0.3.1.tar.gz
- Upload date:
- Size: 8.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85ec7bde14acebd6f7ea155d8535eb3dcc1bd85adde91c1fce424aecf9e207a5
|
|
| MD5 |
145847cc4b1635d1fb3cfebd2a6dff62
|
|
| BLAKE2b-256 |
b924e7c029277ce5a408d426b5e92e07767836b69e9a28d696ef7ea18242ccfd
|
Provenance
The following attestation bundles were made for dograh_ctl-0.3.1.tar.gz:
Publisher:
release.yml on erickcxc/dograh-ctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dograh_ctl-0.3.1.tar.gz -
Subject digest:
85ec7bde14acebd6f7ea155d8535eb3dcc1bd85adde91c1fce424aecf9e207a5 - Sigstore transparency entry: 2557735017
- Sigstore integration time:
-
Permalink:
erickcxc/dograh-ctl@77e0efebc840a6b0b6ec1c072e787ce8fdb28680 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/erickcxc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@77e0efebc840a6b0b6ec1c072e787ce8fdb28680 -
Trigger Event:
push
-
Statement type:
File details
Details for the file dograh_ctl-0.3.1-py3-none-any.whl.
File metadata
- Download URL: dograh_ctl-0.3.1-py3-none-any.whl
- Upload date:
- Size: 35.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ea8e0347120f78e017ab007069aa11a08cab7c35b030326d42152ed431db8759
|
|
| MD5 |
13b823b5976dd6ce0850c6e1b79c394f
|
|
| BLAKE2b-256 |
e4c97ee879082ef385dddd893fe4fa7588814c1f5024b4fbda38566f5d443671
|
Provenance
The following attestation bundles were made for dograh_ctl-0.3.1-py3-none-any.whl:
Publisher:
release.yml on erickcxc/dograh-ctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
dograh_ctl-0.3.1-py3-none-any.whl -
Subject digest:
ea8e0347120f78e017ab007069aa11a08cab7c35b030326d42152ed431db8759 - Sigstore transparency entry: 2557735126
- Sigstore integration time:
-
Permalink:
erickcxc/dograh-ctl@77e0efebc840a6b0b6ec1c072e787ce8fdb28680 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/erickcxc
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@77e0efebc840a6b0b6ec1c072e787ce8fdb28680 -
Trigger Event:
push
-
Statement type: