Skip to main content
An agent is a versioned graph of nodes. The runtime compiles the graph to a LangGraph and streams a tool-call trace as it executes.

Graph shape

  • agent node - a model (provider/model), a system prompt, and the tool ids it may call.
  • tool node - executes the referenced tools and returns results to the agent.
  • router node - optional branching. Static by default; a decision router asks the decision model which branch to take (below).
  • edges - connect nodes; __end__ terminates the run.
A typical ReAct loop: agent → tools → agent, with agent → __end__ when the model has its answer.

Decision routers

A router with mode: "decision" puts a choice question to the decision model (TypeSafe’s Jev, through the workspace’s TypeSafe or OpenRouter connection) over its branch names, and takes the winner. The model reads the last user message, the last assistant reply, and each branch’s description. There is no prompt to write and no label to parse: the answer is a distribution, and the trace keeps it.
Below minConfidence (default 0.5) the pick is not trusted. onLowConfidence is default (take the default branch) or ask_human (the run pauses with the options and continues on the branch the person names, by name or number). If the decision model is unreachable the router takes default and records why. Every pick is a decision step in the run’s trace, with the choice, its confidence and the probability per branch, and its cost is metered on the run. Two things to know when writing the branches. The model always picks one of them, and confidence says how concentrated the distribution is, not whether any option fits: a greeting sent to a router with only billing and delivery comes back as one of them at high confidence. Give the router an explicit other branch (usually pointing at the same node as default) so off-list messages have somewhere to go. And an agent you compare in evals should use onLowConfidence: "default": a run that pauses to ask a person has nobody to answer inside an eval and is recorded as a failed cell.

The decide tool

The decide built-in lets an agent ask the same model itself. A yes/no statement about some text returns { "probability": 0.91 }; a question with options returns { "choice", "confidence", "probabilities" }. The agent passes the relevant text as context. Use it where the agent must sort, escalate or branch on a judgement rather than prose: “this ticket is urgent”, “which supplier matches this invoice”. Add it from Tools like any other built-in; each call shows in the trace as a decision step.

Versions

Each agent has numbered versions. Publishing a version points the agent at it. cruqai push compiles an authoring file and publishes a new version.

Running

Runs and their tool-call traces are persisted and visible in AI Monitoring and via cruqai runs / cruqai trace. See Observability. An agent can also run without you: on a recurring schedule, or in response to an inbound channel message. A run does not have to finish in one pass either. It can pause for a person, wait until a later time, keep a plan across a long task, and check its own work before finishing: see Long-running agents.

Choosing the model

Each agent node names one model, and swapping it is a change to the graph rather than to any code. That makes the model a variable you can measure instead of guess at: Evals runs a fixed suite of test cases across several models and ranks them on score, latency, and cost.