Typed decisions with TypeSafe
Use TypeSafe when the next step must be a closed set: allow / block / review, a risk score, a yes-no human gate. Do not use it to draft tickets, write code, or run a tool loop. Those stay on an LLM connection via ai.chat.
Connect the key first: TypeSafe. The only featured workflow is typesafe.systemone.evaluate.
typesafe.systemone.evaluate. Everything below is that same atomic, placed as a step. There is no separate TypeSafe app, and Staff does not auto-triage the inbox with Jev until you compose it.What to use where
| Surface | What TypeSafe does | What still uses an LLM |
|---|---|---|
| Compositions | First layer: evaluate, then later layers map answers.* | Optional later steps that draft or explain |
| Staff actors | An allowed MCP call before a mutating workflow | The actor's model provider (OpenAI, Anthropic, …) |
| DGI | Classify intent / domain / complexity as a compiled step | Goal prose and DAG assembly |
Kaoitos / kubernetes.* | Score or noul before a destructive cluster action | None required for the gate |
| Tickets | page / priority / routine / deferred on an incoming envelope | Plan and patch generation |
The pattern is always: decide, then spend. Jev labels; chat models generate.
Compositions
A composition is layers of existing catalog types. Put evaluate in layer 1. Pin the question set as static so callers cannot widen it. Pass connection_uuid and state from the composition input.
{
"name": "decide-then-act",
"layers": [
{
"name": "decide",
"steps": [
{
"name": "jev",
"workflow_type": "typesafe.systemone.evaluate",
"input_mapping": {
"connection_uuid": { "source": "input", "field_name": "connection_uuid" },
"state": { "source": "input", "field_name": "state" },
"questions": {
"source": "static",
"value": {
"action": {
"type": "choice",
"instructions": "What should we do?",
"criteria": {
"allow": "Safe to proceed",
"block": "Must not proceed",
"review": "Needs a human"
}
},
"needs_human": {
"type": "noul",
"instructions": "Does this need a human in the loop?"
}
}
}
}
}
]
}
]
}
Save with composition.validate then composition.save. Invoke virtual.<uuid>@<version> like any other type. To share it with app end-users, follow Compositions.
Next layers read answers.action and answers.needs_human from the jev step (source: "step"). Keep mutating workflows after the decide layer so a block never reaches them.
Authoring is the same whether you hand-write JSON, use the console DAG builder, DevKit, or DGI: all of them compile to this representation.
Staff
Staff actors reason with an LLM connection. TypeSafe is not one of those. Do not add the TypeSafe key as the actor's model provider.
What works today:
- Connect TypeSafe in the main app, not in Staff.
- Give the actor MCP / skill access to start
typesafe.systemone.evaluate(same as any other catalog type). Staff RBAC still governs who may start it. - In standing instructions, tell the actor when to call it (for example: before
start_workflowon a mutating type, or when classifying an inbox envelope into page / priority / routine / deferred).
The actor still needs a real model provider and an agent-eligible runner group. Jev is a tool the session may call, not the brain.
TYPESAFE_API_KEY in Staff or actor environment. The workflow decrypts the org connection in-process, the same rule as LLM keys.DGI
Building with DGI turns a prompt into a composition. Ask it for a first step that is typesafe.systemone.evaluate with a fixed question set, then later steps that consume answers. DGI still writes the goal prose; TypeSafe only labels.
DGI is alpha. Treat the compiled composition as the artifact you review, not the chat that produced it.
Cluster and runner actions
For Kaoitos and runner mutations, the useful TypeSafe questions are a score (how risky) and a noul (needs a human). Put evaluate in the composition ahead of kubernetes.* or runner.* steps that create, scale, or delete. A block or needs_human: true should stop the composition before those steps run.
Tickets and software delivery
The ticket-to-PR path already has human gates. TypeSafe is a cheap prefilter on the incoming envelope (page this, batch that), not a replacement for acknowledged plans or PR review.
What not to do
- Do not point TypeSafe at
ai.chator LiteLLM. - Do not use it as the Staff actor model.
- Do not send secrets, kubeconfigs, or raw credentials in
state. - Do not treat connect/test (empty
/systemoneprobe) as an evaluation. That probe only checks the key.
Reference
- Connection setup: TypeSafe
- Schema and errors: reference.orkestia.dev/typesafe
- MCP loop: Connect an AI assistant
