Get started
Run your first local workflow
Install the engine, define a sequence, schedule a task. No JVM, no Cassandra, no Elasticsearch. One binary, one database.
Install
Pick one:
curl -fsSL https://orch8.io/start.sh | shbrew tap orch8-io/orch8 && brew install orch8-serverdocker run -d -p 8080:8080 ghcr.io/orch8-io/engine:0.7.0 --insecureThe Docker image uses SQLite by default — no external database needed for local development.
Start the engine
By default the engine requires an API key for authentication. For local development, run with --insecure to skip auth:
orch8-server --insecureFor production, set an API key via environment variable:
export ORCH8_API_KEY="your-secret-key"
orch8-serverSQLite initializes its embedded schema automatically and the engine starts listening on port 8080. PostgreSQL migrations are opt-in.
Note: If the command is not found, make sure the install directory (usually ~/.local/bin) is in your PATH.
For production with Postgres:
docker run -d \
-e ORCH8_STORAGE_BACKEND=postgres \
-e ORCH8_DATABASE_URL=postgres://user:pass@host:5432/orch8 \
-e ORCH8_RUN_MIGRATIONS=true \
-e ORCH8_ENCRYPTION_KEY=<64-hex-chars> \
-e ORCH8_API_KEY=<your-api-key> \
-p 8080:8080 \
ghcr.io/orch8-io/engine:0.7.0Define a sequence
A sequence is a series of steps the engine will execute durably. Create one with a POST request:
curl -X POST http://localhost:8080/api/v1/sequences \
-H "Content-Type: application/json" \
-d '{
"tenant_id": "demo",
"namespace": "default",
"name": "welcome-flow",
"id": "550e8400-e29b-41d4-a716-446655440000",
"version": 1,
"created_at": "2026-07-28T00:00:00Z",
"blocks": [
{
"type": "step",
"id": "send_welcome",
"handler": "http_request",
"params": {
"url": "https://httpbin.org/post",
"method": "POST",
"body": {
"to": "{{context.data.email}}",
"message": "Welcome, {{context.data.name}}!"
}
}
},
{
"type": "step",
"id": "wait_then_followup",
"handler": "log",
"delay": { "duration": 10000 },
"params": {
"message": "Following up with {{context.data.name}}"
}
}
]
}'The response returns a sequence ID. Copy it for the next step.
Schedule a task instance
curl -X POST http://localhost:8080/api/v1/instances \
-H "Content-Type: application/json" \
-d '{
"sequence_id": "<sequence-id-from-step-2>",
"tenant_id": "demo",
"namespace": "default",
"priority": "Normal",
"context": {
"data": {
"email": "jane@example.com",
"name": "Jane"
}
}
}'The engine picks up the instance, executes the first step immediately, waits 10 seconds, then runs the follow-up. If the engine crashes and restarts, it resumes from the last completed step.
Check the status
# Get instance state
curl http://localhost:8080/api/v1/instances/<instance-id>
# See step outputs
curl http://localhost:8080/api/v1/instances/<instance-id>/outputsControl it
# Pause
curl -X POST http://localhost:8080/api/v1/instances/<instance-id>/signals \
-H "Content-Type: application/json" \
-d '{ "signal_type": "Pause" }'
# Resume
curl -X POST http://localhost:8080/api/v1/instances/<instance-id>/signals \
-H "Content-Type: application/json" \
-d '{ "signal_type": "Resume" }'
# Cancel
curl -X POST http://localhost:8080/api/v1/instances/<instance-id>/signals \
-H "Content-Type: application/json" \
-d '{ "signal_type": "Cancel" }'Use an SDK instead of curl
Install an official SDK and manage everything from code:
Node.js / TypeScript
npm install @orch8.io/sdkimport { Orch8Client } from "@orch8.io/sdk";
const client = new Orch8Client({ baseUrl: "http://localhost:8080/api/v1" });
// Create a sequence
const seq = await client.createSequence({
tenant_id: "demo",
namespace: "default",
name: "welcome-flow",
blocks: [{
type: "step",
id: "greet",
handler: "log",
params: { message: "Hello, {{context.data.name}}!" },
}],
});
// Schedule an instance
const instance = await client.createInstance({
sequence_id: seq.id,
tenant_id: "demo",
namespace: "default",
context: { data: { name: "Jane" } },
});
console.log("Instance:", instance.id);Python
pip install orch8-io-sdkimport asyncio
from orch8 import Orch8Client
async def main():
client = Orch8Client(base_url="http://localhost:8080/api/v1")
seq = await client.create_sequence({
"tenant_id": "demo",
"namespace": "default",
"name": "welcome-flow",
"blocks": [{
"type": "step",
"id": "greet",
"handler": "log",
"params": {"message": "Hello, {{context.data.name}}!"},
}],
})
instance = await client.create_instance({
"sequence_id": seq.id,
"tenant_id": "demo",
"namespace": "default",
"context": {"data": {"name": "Jane"}},
})
print(f"Instance: {instance.id}")
asyncio.run(main())Go
go get github.com/orch8-io/sdk-gopackage main
import (
"context"
"fmt"
orch8 "github.com/orch8-io/sdk-go"
)
func main() {
client := orch8.NewClient(orch8.ClientConfig{
BaseURL: "http://localhost:8080/api/v1",
})
ctx := context.Background()
seq, _ := client.CreateSequence(ctx, map[string]any{
"tenant_id": "demo",
"namespace": "default",
"name": "welcome-flow",
"blocks": []map[string]any{{
"type": "step",
"id": "greet",
"handler": "log",
"params": map[string]any{"message": "Hello!"},
}},
})
inst, _ := client.CreateInstance(ctx, map[string]any{
"sequence_id": seq.ID,
"tenant_id": "demo",
"namespace": "default",
})
fmt.Println("Instance:", inst.ID)
}What next?
Full documentation
Complete API reference, block types, handlers, and configuration
22 real-world patterns
Payment failover, email campaigns, AI agents, circuit breakers
Starter templates
SaaS onboarding, AI support triage, invoice processing
SDKs & CLI
Node.js, Python, Go SDKs and the orch8 CLI
GitHub
Source code, issues, and contributing