Canvas
Install the local builder, then open a graph file.
npx splinel
splinel open ./paths/support-triage.spline.json
The canvas reads a path JSON. Nodes sit still. Spline-blue edges connect them. The deploy node wears the hub-gold lock once you publish a version.
Nodes
Each node has an id, a kind, and typed ports. The sample on Product is this seven-node support triage path.
{
"path_id": "pth_support_triage_v3",
"name": "Support triage",
"version": 3,
"deploy": {
"mode": "api",
"url": "https://run.splinel.xyz/v1/paths/pth_support_triage_v3/run",
"lock": "hub"
},
"nodes": [
{ "id": "inbox", "kind": "trigger.http", "next": ["classify"] },
{ "id": "classify", "kind": "model.generate", "model": "anthropic.claude-sonnet-4", "next": ["crm"] },
{ "id": "crm", "kind": "tool.hubspot.lookup", "next": ["draft"] },
{ "id": "draft", "kind": "model.generate", "model": "anthropic.claude-sonnet-4", "next": ["review"] },
{ "id": "review", "kind": "gate.human", "next": ["deploy"] },
{ "id": "deploy", "kind": "action.resend.send", "lock": true, "next": ["trace"] },
{ "id": "trace", "kind": "observe.cost" }
]
}
Secrets
Store provider keys in the vault. Reference them as secret://openai on a node. Sketch keeps secrets in ~/.splinel/vault with mode 0600. Path and Hub keep them in the regional vault. Rahul’s team never reads customer secret values in plaintext support tickets.
Deploy
Publish a version, receive a URL and a key.
splinel deploy ./paths/support-triage.spline.json -v 3
The lock writes a URL on run.splinel.xyz and a key prefixed sk_live_, scoped to that path and version.
Tracing
GET a run by id. The waterfall on the home page is run 8f21 of this path: classify $0.0041, crm $0.0000, draft $0.0186, review $0.0000, send $0.0004, total $0.0231 in 1.84s.
Self-host
The Apache-2.0 compose file runs canvas, vault, and runner on your network. Point SPLINEL_DATA at a disk you control. Hub VPC is the managed cousin of this layout.
git clone https://github.com/splinel/splinel.git
cd splinel
docker compose -f deploy/self-host.yml up
Ollama and hosted models
Local: set a node model to ollama.llama3.1:8b and start Ollama on port 11434. Hosted: OpenAI, Anthropic, Google Gemini, Groq, Mistral, Azure OpenAI, Cohere, Fireworks, Together. Mix both on one path. The classify node can be local while draft uses Sonnet.
API
Run a deployed path. OpenAPI lives at https://run.splinel.xyz/openapi.json.
curl -X POST https://run.splinel.xyz/v1/paths/pth_support_triage_v3/run \
-H "Authorization: Bearer sk_live_splinel_demo_9f3a2c" \
-H "Content-Type: application/json" \
-d '{"ticket_id":"TCK-1842","queue":"billing"}'
Response:
{
"run_id": "run_8f21",
"path_id": "pth_support_triage_v3",
"version": 3,
"status": "ok",
"duration_ms": 1840,
"cost_usd": 0.0231,
"output": {
"sent_message_id": "re_01HZX4",
"classification": "billing.refund"
}
}
Webhooks
Create an inbound URL per path. Splinel verifies X-Splinel-Signature (HMAC-SHA256 of the body). Zendesk, Stripe, and GitHub connectors sign with that header. Outbound webhooks fire after the deploy node with the same run payload.
Trace export
curl -X GET https://run.splinel.xyz/v1/runs/run_8f21 \
-H "Authorization: Bearer sk_live_splinel_demo_9f3a2c"
Hub can dump 90 days of runs as JSONL to S3. Path keeps 14 days in the UI.
Questions: [email protected]