AI does the work. You make the calls.
LLM task orchestration engine — split any goal into a real dependency graph,
route tasks to specialized AI agents, pause for human approval, and resume automatically.
API Docs · Get API Key · Website
Orchflow is in public beta. The core workflow engine is working, but the product is still being actively refined based on real user feedback.
You're building a product that needs multi-step AI workflows — research, draft, review, approve, publish. You need some steps to pause for human input. You need runs to survive server restarts. You need different AI models for different task types.
Building this infrastructure yourself takes weeks. Orchflow gives you a REST API that handles it.
Without Orchflow With Orchflow
──────────────────────────────── ─────────────────────────────────────
Build your own: POST /api/v1/runs
✗ State machine {
✗ DAG execution "task": "Create a blog post about AI",
✗ Retry logic "agents": [{
✗ Human approval gates "name": "research",
✗ Webhook system "system_prompt": "You are an expert..."
✗ Crash recovery }],
✗ Multi-model routing "human_gates": ["approve"],
"provider_id": "prv_abc123"
~3 weeks of infra work }
← run_id returned in milliseconds
← executes in background
← pauses when human input needed
← resumes when you respond
| Hosted | Self-hosted | |
|---|---|---|
| Setup | Register → run | Clone → Docker → run |
| Trial runs | 3 managed runs included | BYOK from the start |
| Your data | Our VPS | Your infrastructure |
| Config | ORCHFLOW_MODE=hosted |
ORCHFLOW_MODE=self_hosted |
Same engine. Same API. Different deployment policy.
New users get 3 managed trial runs. Register, start a run, see it work, then add your own provider key when you are ready.
curl -X POST https://api.orchflow.cloud/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"name": "Your Name", "email": "you@example.com"}'curl -X POST https://api.orchflow.cloud/api/v1/runs \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{
"task": "Plan and launch a faceless YouTube channel about AI tools for freelancers. Research 5 competing channels, extract content patterns, define our positioning, design a 30-day content plan, and produce a launch checklist.",
"agents": [
{ "name": "research" },
{ "name": "analyst" },
{ "name": "writer" }
],
"ask_me_about": ["brand voice", "target audience"],
"require_approval": false
}'{
"run_id": "run_abc123",
"status": "pending",
"message": "Run started. Poll GET /runs/run_abc123 for status."
}# Poll status
curl https://api.orchflow.cloud/api/v1/runs/run_abc123 \
-H "X-API-Key: orch_your_key"
# When status = "waiting_human" - submit missing context
curl -X POST https://api.orchflow.cloud/api/v1/runs/run_abc123/tasks/T1/complete \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{"output": "Brand voice should be practical and founder-friendly. Target audience is solo freelancers and small agencies."}'The run resumes automatically. Your answer becomes context for the next AI task.
curl -X POST https://api.orchflow.cloud/api/v1/providers \
-H "X-API-Key: orch_your_key" \
-H "Content-Type: application/json" \
-d '{"provider": "gemini", "api_key": "your_gemini_key", "label": "My Gemini key"}'{ "provider_id": "prv_abc123" } // pass this in runs after your managed trialPOST /runs
│
▼
split_tasks ──── LLM splits your goal into 3–6 subtasks
│
▼
infer_deps ───── LLM builds a real dependency graph (not a linear chain)
│
▼
assign_agents ── Tasks routed to your registered agents by name match
│
▼
execute loop ─── Each task runs with full context from all prior tasks
│ │
│ ⏸ human gate fires
│ → run suspends
│ → webhook notifies you
│ → you submit input via API
│ → run resumes with your input as context
▼
finalize ──────── All outputs synthesized into one coherent result
| Feature | Direct LLM call | Orchflow |
|---|---|---|
| Multi-step execution | ✗ manual | ✅ automatic DAG |
| State persistence | ✗ none | ✅ Redis + Postgres |
| Human approval gates | ✗ not possible | ✅ suspend + resume |
| Survives server restart | ✗ | ✅ |
| Multi-day workflows | ✗ | ✅ |
| Specialized agents | ✗ one prompt | ✅ named agents with roles |
| Self-evaluation + retry | ✗ | ✅ up to 2 retries |
| Webhook notifications | ✗ | ✅ |
Copy any template into your agents array and customize the system_prompt:
research — expert research analyst
{
"name": "research",
"system_prompt": "You are an expert research analyst. Find relevant facts, statistics, and insights. Structure your output clearly. Cite your reasoning."
}coding — senior software engineer
{
"name": "coding",
"system_prompt": "You are a senior software engineer. Write clean, well-commented, production-ready code. Follow best practices. Include error handling."
}writer — professional content writer
{
"name": "writer",
"system_prompt": "You are a professional content writer. Write clearly and engagingly for the target audience. Use good structure. Be concise but complete."
}analyst — senior data analyst
{
"name": "analyst",
"system_prompt": "You are a senior data analyst. Analyze information objectively. Identify patterns and trends. Provide actionable insights with summary, findings, and recommendations."
}editor — senior editor
{
"name": "editor",
"system_prompt": "You are a senior editor. Review critically but constructively. Improve clarity, flow, and impact. Fix inconsistencies. Provide specific, actionable feedback."
}All templates: GET /api/v1/agents/templates
| Provider | Default model | Notes |
|---|---|---|
gemini |
gemini-2.0-flash-lite |
Recommended for most tasks |
openai |
gpt-4o-mini |
Strong for reasoning + code |
anthropic |
claude-3-5-haiku-20241022 |
Best for writing + editing |
ollama |
llama3 |
Self-hosted, fully private |
Use different models per agent — route coding tasks to GPT-4o, writing to Claude:
{
"agents": [
{ "name": "research", "system_prompt": "...", "model": "gemini-2.0-flash-lite" },
{ "name": "coding", "system_prompt": "...", "model": "gpt-4o" }
]
}Content agency tool — client submits a brief, AI researches and writes, human editor approves before publish:
import requests
ORCHFLOW_KEY = "orch_your_key"
BASE = "https://api.orchflow.cloud/api/v1"
def start_content_workflow(brief: str, editor_webhook: str) -> str:
r = requests.post(f"{BASE}/runs",
headers={"X-API-Key": ORCHFLOW_KEY},
json={
"task": brief,
"agents": [
{"name": "research"},
{"name": "analyst"},
{"name": "writer"},
],
"ask_me_about": ["client goals", "brand voice", "must-avoid claims"],
"require_approval": False,
"webhook_url": editor_webhook,
}
)
return r.json()["run_id"] # returns instantly, runs in background
# Webhook fires when human context is needed
# payload: {run_id, event: "waiting_human", waiting_tasks: ["T3"]}
def answer_orchflow(run_id: str, task_id: str, answer: str):
requests.post(
f"{BASE}/runs/{run_id}/tasks/{task_id}/complete",
headers={"X-API-Key": ORCHFLOW_KEY},
json={"output": answer}
)
# Run resumes automatically - your answer becomes context for the next taskThe run can span hours or days. State persists across server restarts. Orchflow handles everything in between.
| Field | Use it when | Example |
|---|---|---|
ask_me_about |
Orchflow should pause early and ask for missing context before AI continues | ["target audience", "brand voice"] |
human_gates |
You want specific planned steps to be completed by a human | ["legal approval", "founder review"] |
require_approval |
You want every AI task to wait for human approval | true |
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/v1/auth/register |
Register and get API key |
POST |
/api/v1/providers |
Register an LLM provider key (AES-GCM encrypted) |
GET |
/api/v1/providers |
List registered providers |
DELETE |
/api/v1/providers/{id} |
Deactivate a provider |
POST |
/api/v1/runs |
Start a run |
GET |
/api/v1/runs |
List run history |
GET |
/api/v1/runs/{id} |
Run status + full task tree |
GET |
/api/v1/runs/{id}/tasks |
All tasks, works mid-run |
POST |
/api/v1/runs/{id}/tasks/{tid}/complete |
Submit human task output |
DELETE |
/api/v1/runs/{id} |
Cancel a run |
GET |
/api/v1/agents/templates |
Prebuilt agent system prompts |
Interactive docs: api.orchflow.cloud/docs
git clone https://github.com/RunProgrammer/orchflow
cd orchflow
# 1. Generate encryption key for provider key storage
python -c "import secrets,base64; print(base64.b64encode(secrets.token_bytes(32)).decode())"
# 2. Configure
cp .env.example .env
# Set: GEMINI_API_KEY, ENCRYPTION_KEY, DATABASE_URL, REDIS_URL
# 3. Start
docker compose up -d
# 4. Apply migrations
alembic upgrade head
# 5. Verify
curl http://localhost:8000/healthRequirements: Docker, Docker Compose. Nothing else.
# Hosted — 3 managed trial runs, then BYOK
ORCHFLOW_MODE=hosted
MANAGED_TRIAL_RUNS_ENABLED=true
MANAGED_TRIAL_RUNS_COUNT=3
ALLOW_MANAGED_RUNS_WITHOUT_PROVIDER=true
# Self-hosted — BYOK from the start
ORCHFLOW_MODE=self_hosted
MANAGED_TRIAL_RUNS_ENABLED=false
MANAGED_TRIAL_RUNS_COUNT=0
ALLOW_MANAGED_RUNS_WITHOUT_PROVIDER=falseSame engine. One env var changes the deployment behavior.
Shipped
- LLM-generated DAG execution
- Human-in-loop suspend + resume
- Multi-LLM support (Gemini, OpenAI, Anthropic, Ollama)
- Encrypted provider key storage (AES-GCM)
- Named agents with custom system prompts
- Shared run context across all agents
- Self-evaluation with retry and escalation
- Webhook notifications
- Run history + cancellation
- Config-driven hosted / self-hosted modes
Coming
- Persistent agent registry — register once, reuse across runs
- Python SDK —
pip install orchflow - Tool calling per agent — web search, code execution
- Skill-based human routing — route to the right team member
- Run history dashboard
Issues and PRs welcome. See CONTRIBUTING.md for guidelines.
{ "api_key": "orch_...", // save this - shown once "message": "Free tier: 100 runs/month, 3 managed trial runs included." }