Typed decisions with TypeSafe

Connect TypeSafe Jev, run typesafe.systemone.evaluate, and put typed choice, score, and noul answers in front of compositions and Staff.

Orkestia5 min read

Orkestia is the backbone that connects software, AI, and the real world. Most of the catalog does something in that world: create a bucket, scale a deployment, open a ticket. TypeSafe Jev does something else. It looks at unstructured context, answers questions you already wrote, and returns values the next workflow can consume without parsing prose.

The capability is live. The workflow type is typesafe.systemone.evaluate. TypeSafe is not a chat model, not OpenAI-compatible, and not a Staff actor brain. Connect it as TypeSafe. Call it as a workflow. Put it in front of the work that costs money.

What you get back

You send state (the situation) and questions (the closed set). Each question is one of three kinds:

  • choice: pick one key from a criteria object (allow, block, review)
  • score: pick one level from an ordered list (low, medium, high)
  • noul: yes or no

The run finishes with answers keyed the same way as questions. That is the whole product surface. There is no TypeSafe chat endpoint, and there is no built-in Staff inbox that auto-triages with Jev. You compose the evaluate step yourself.

Connect it once

Create a TypeSafe API key, then create an org-scoped connection with provider type typesafe. Required field: api_key. The key is stored encrypted on the connection. It does not go in Staff env, actor env, or workflow inputs.

Connect/test posts an empty body to TypeSafe's /systemone. A 401 is a bad key. A 400 or 422 means the key authenticated without spending an evaluation. Real decisions go through typesafe.systemone.evaluate and are billed to your TypeSafe account.

Do not paste a TypeSafe key into an openai or openrouter connection. Those providers talk to chat-style endpoints. TypeSafe has none.

Setup and the input schema are in the docs: TypeSafe connection.

Run it from MCP

Same loop as any other capability. Confirm identity, read the schema, start, watch.

whoami()
get_workflow_schema("typesafe.systemone.evaluate")
start_workflow(workflow_type="typesafe.systemone.evaluate", initial_data={...})
watch_workflow(workflow_id)

A minimal payload looks like this:

{
  "connection_uuid": "<typesafe-connection-uuid>",
  "state": "The change deletes production with no rollback plan.",
  "questions": {
    "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?"
    }
  }
}

connection_uuid is required. model is optional and defaults to jev-latest. Read answers on the finished run before you start anything that mutates.

Put it in a composition

A composition is layers of existing catalog types. That is the right place for TypeSafe, because the next step can map answers.action without an agent reinterpreting the verdict.

Pin the question set as static so callers cannot widen it. Pass connection_uuid and state from the composition input. Keep mutating workflows in a later layer, after evaluate has finished.

{
  "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"
                  }
                }
              }
            }
          }
        }
      ]
    }
  ]
}

Save with composition.validate then composition.save. Invoke virtual.<uuid>@<version> like any other type. Authoring is the same whether you write JSON, use the console DAG builder, DevKit, or DGI: all of them compile to this representation.

The longer walkthrough, including how later layers read answers.*, is Typed decisions with TypeSafe. Compositions themselves are documented at Creating and exposing virtual workflows.

Use it from Staff, as a tool

Staff actors reason with an LLM connection you already have: OpenAI, Anthropic, Azure OpenAI, and the rest of the model-provider list. TypeSafe is not on that list. Do not hire an actor against a TypeSafe connection.

What works today:

  1. Connect TypeSafe in the main app, not in Staff.
  2. Allow the actor to start typesafe.systemone.evaluate through MCP, the same way it starts any other catalog type. Staff RBAC still governs who may run it.
  3. In standing instructions, say when to call it. Before a mutating start_workflow is the common case. Classifying an inbox envelope into page, priority, routine, or deferred is another.

The actor still needs a real model provider and an agent-eligible runner group. Jev is a tool the session may call, not the model that writes the session.

Never put TYPESAFE_API_KEY in Staff or actor environment. The workflow decrypts the org connection in-process.

Other places it fits

Same atomic, different first layer:

DGI. Ask DGI for a composition whose first step is typesafe.systemone.evaluate with a fixed question set. DGI still writes the goal prose. TypeSafe only labels. Review the compiled composition, not the chat that produced it. DGI is alpha.

Cluster and runner mutations. A score plus a noul in front 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. A cheap prefilter on an incoming envelope (page this, batch that). It does not replace acknowledged plans or pull request review.

The pattern is always decide, then spend. Jev labels. Chat models generate. Mutating workflows run last.

What not to do

  • Do not point TypeSafe at ai.chat or 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 as an evaluation. That probe only checks the key.

If you get stuck, write to hello@orkestia.dev. A real person reads it.

  • typesafe
  • workflows
  • compositions
  • staff