Theo Agents

Theo Agentsare the user-visible brand for OpenCharts' persistent agent platform. Each Theo Agent owns a name, an icon, a trigger, a step graph, a sharing visibility, and an optional verification badge — and runs on the same EVI runtime that powered the legacy Automation Designer. Build one in the Designer, run it manually or on a schedule, share it with your org, and the Library lets your teammates install a verified copy with one click.

Where Theo Agents liveThe dashboard is at /theo-agents. The Designer is at /theo-agents/[id] and opens as a dedicated full-page workspace — the regular sidebar + dashboard header step out of the way so you can focus on the agent. The Library is at /theo-agents/library. Run history at /theo-agents/[id]/runs. Insights at /theo-agents/[id]/insights. Legacy /automations and /steelagents URLs 308 to the matching Theo Agents route so existing bookmarks keep working.

Two kinds of agents

Workflow agents

Deterministic step-by-step pipelines built in the visual Designer. Best when the shape of the work is known in advance — fetch, transform, post, notify.

Autonomous agents (coming soon)

Goal-driven agents that compose their own steps at runtime are on the roadmap. The Workflow ↔ Autonomous toggle is hidden in the Designer until that runtime ships — today every agent runs as a deterministic Workflow, so build your agents as explicit step graphs.

In the Designer

  • Dedicated full-page canvas — the Designer drops the global sidebar + header so the agent is the only thing on screen. A slim breadcrumb keeps you anchored and a single click on the emblem takes you back to Mission Control.
  • Run vs Test — the Test button does a free dry-run with live per-step status, while the Run button fires a real, credit-consuming run that lands in Run history. For a manual-trigger agent the Run button is the primary action (nothing fires it automatically); you can also run any agent on demand from its card’s actions menu or the Run history page.
  • Drag-and-drop StepLibrary with the live step kinds: action (connector), theo_action (AI action), path (branching), approval (human gate), delay, and call_agent (sub-agent dispatch).
  • TheoBuilderRail — natural-language co-builder. Tell Theo "add a step that summarises last week's Stripe payments and posts to Slack" and watch the canvas update. One clear close button on the rail, an ‘Ask Theo’ pill that brings it back, and your collapse choice is remembered across reloads.
  • Delay step — pause the flow for a short, fixed wait (up to 2 minutes) before the next step runs. Longer or recurring waits belong on a scheduled trigger instead.
  • Wait for Approval (human gate) — the agent pauses and pings you in Telegram (and the in-app bell) with Accept / Reject buttons. Approving resumes the run right where it left off; a paused agent waiting on you is never counted as a failure.
  • Per-step model + temperature override for theo_action steps so you can pin a specific engine on a step without changing the rest of the agent.
  • Scheduled agents get the same time budget as a manual run, so a multi-step agent on a schedule finishes instead of being cut off early.

Steps are still authored as the same AutomationStep[] JSON the legacy Automations Designer used — Theo Agents is a brand-level rename plus the new agent-aware features (per-step model controls, verification, library, feedback). The underlying /api/automations/* + /api/steelagents/* endpoints and the automations collection are unchanged.

Paths & conditions

A Path step splits the chain into parallel branches that re-converge once one of them completes. The Designer renders the split as a contained Parallel branches panel that sits inside the path card via a hairline separator — same lane width as the rest of the chain, no breakout, no horizontal scroll. Branches stack vertically inside the panel; the layout looks identical at 360px and 1920px and grows downward gracefully no matter how many branches you add.

Each branch is a full-lane-width branch card with a left-edge accent stripe — blue for indexed branches, amber for the default. The card header carries a Branch N / Default chip, an inline label input (If match / Else / whatever you type), and a kebab menu (⋯) with the branch-level actions (see below).

Below the header, every labeled branch shows an always-visible inline condition editor with three knobs:

  • Field — the upstream output key to test, picked from a context-aware dropdown that groups From trigger first, then one section per upstream step (e.g. From Step 1 — Theo Decision). Each entry shows a one-line description from the skill’s output schema so you know why decision, summary, or sent appears. Choose Custom path… at the bottom of the list to type a freeform dot-path like triggerData.customer.email for connector-specific or webhook-payload keys the registry doesn’t model. Leave blank to fall back to the path step’s default subject set on the expanded path card.
  • Operator — one of equals, does not equal,>, >=,<, <=,contains, starts with, plus the unary checks exists, is truthy, and is falsy / empty. Numeric operators coerce both sides; contains and starts with are case-insensitive.
  • Value — what the field is compared to. Hidden automatically when the operator is unary (exists / truthy / falsy).

The kebab menu (⋯) on each branch card hosts the less-frequent actions: Mark as default branch (promotes the lane to the explicit “else”, replaces the condition editor with Runs when no other branch matches), Custom expression (collapses the structured editor to a single freeform condition string the runtime matches against input.decision / result / value), and Delete branch.

Below the editor, each branch carries its own Then step chain — the same full-width <StepCard> chrome the main lane uses, plus an + Add step button at the bottom. Adding the 3rd, 4th, 10th branch just extends the panel downward; no fan-out, no per-lane width compromise, no horizontal scroll. The panel ends with an ↓ All branches continue here marker that anchors the run back into the main chain.

Runtime contract. At save time the EVI adapter rewrites each branch onto an edge labelled branch_0, branch_1, … (or default for the else branch). The switch executor walks the branches in order, evaluates each expression against the upstream input, and emits { decision: "branch_<i>" } for the first match. If nothing matches and there is no default branch the path fails the step with an actionable error — silent dead-ends are intentional bugs that the validation banner also warns about before you can Go Live.

Every new path you add starts seeded with one structured “If match” branch + one explicit “Else” default. Add more branches with the Add branch button; the editor keeps the default trailing so the visual order matches the runtime fall-through order.

Heads-up validation. When a branch references a field key no upstream trigger or step is known to emit, the Designer surfaces a neutral Heads up note above the canvas with a suggestion to pick from the dropdown or switch to the Custom path option. This is advisory only — it never blocks Test or Go Live because custom connectors and webhook payloads can legitimately emit keys the registry doesn’t model.

Library, install, and fork

The Library shows every verifiedTheo Agent in the user's org. Clicking Install mints a personal fork of the source agent (verified flag cleared, visibility set to private). Re-installing the same source is idempotent — you always get back the existing fork instead of a duplicate.

The fork carries a forkOfId pointer so future version-pinning work can resolve the right published version. Today the runtime dispatches the live target document; the executor records target.publishedVersion on everycall_agent step output so the insights aggregator can attribute future runs.

How verification works

Verification is what unlocks two things at once: org-wide Library install and cross-user chat dispatch. Until an admin flips the badge, a Theo Agent can only be dispatched by its owner.

  1. Share with the org. In the Designer header, set Visibility to Org. Personal-private agents cannot be verified — they’re scoped to the owner and never appear in the Library.
  2. Ask an admin to verify. Owners and admins of the agent’s org see a Verify button next to the badge cluster in the Designer. Editors and viewers don’t see the button at all — the verify-context route hides it for them.
  3. Click Verify. The Designer POSTs to /api/steelagents/[id]/verify, which runs the canonical gate end-to-end. On success the badge shows Verified and the agent is immediately routable from Theo Chat and installable from the Library. Click again to unverify if you need to pull it back.

All three steps are gated on the verify_steelagents org permission, which defaults to owner + admin.

Dispatch another agent from chat

Theo can route any chat request to one of your routable Theo Agents instead of handling it directly. The agents your org has shared (plus your own private agents) appear in Theo’s Routable Theo Agents system-prompt block; Theo picks the best match and calls route_to_agent to dispatch.

You can also nudge Theo by mentioning an agent explicitly:

  • Use the agent’s slug with an @ prefix — e.g. “kick off the @daily-standup-brief and send it to me”. The chat tool matches case-insensitively and accepts the slug with or without the leading @.
  • Paste the agent’s $id directly when you already have it. Theo Chat looks up the registry first, then falls back to a direct service lookup so the dispatch works even when the agent isn’t in the in-prompt block.

Once Theo dispatches, the chat shows a confirmation card with the agent name, the run link (/theo-agents/[id]/runs), and the thumbs-up / thumbs-down feedback widget. Your rating feeds the agent’s Insights page — every run is attributable to the user who triggered it, so an admin can see real quality signal from chat dispatches.

Three guardrails mirror the runtime call_agent rules above:

  • You can always dispatch agents you own from chat, even when they’re private.
  • Agents owned by another user must be verified and in an org you belong to. Cross-org dispatch is refused.
  • Soft-deleted agents are refused, and Theo will tell you when a route fails so you can correct the reference inline.

Chat-side dispatch is currently gated by the STEELAGENTS_ROUTER server flag. While the flag is off the registry block is empty and Theo Chat treats the tool as disabled.

Sub-agent dispatch (call_agent)

A Theo Agent can call another Theo Agent as a step. Three hard rules govern who can invoke whom:

Same-org-only sub-agent dispatch

A Theo Agent's `call_agent` step can only invoke another Theo Agent in the same org. Cross-org calls are rejected by the executor with a typed permission error — even when the target carries the verified badge.

Cycle detection

The runtime tracks every ancestor automation id in the trigger payload's call stack. Re-entering an agent that's already on the stack (A → B → A) fails fast before any work runs.

Verified-or-owned

A Theo Agent can only call agents it owns or agents that carry the platform `verified` badge. Org admins flip the badge via the `verify_steelagents` permission (env-var + RBAC action names retained for backwards compatibility).

The runtime stamps the caller's org id and a call stack onto the EVI trigger payload before each run; the evi/call-agent executor reads those annotations and short-circuits cross-org / cyclic dispatch before invoking the target.

Feedback & insights

1

Every run gets attribution

Each Theo Agent execution writes an `execution_runs` row keyed by the agent id. The runner is also stamped — only the user who actually executed a run can rate it.

2

Thumbs-up / thumbs-down + comment

The RunFeedbackWidget posts to `POST /api/steelagents/feedback` (API namespace retained for backwards compatibility). Resubmitting upserts the existing row so users can flip their rating without leaving duplicates behind.

3

Insights aggregator

The Insights tab at `/theo-agents/[id]/insights` reads the last 100 runs + every feedback row and renders success rate, average duration, credits per run, feedback score, and the top failure clusters.

Org permissions

Two new actions live on the org permission matrix:

  • manage_steelagents_library — gates the org admin UI for curating categories and approving agents submitted by org members.
  • verify_steelagents — flips the platform-levelautomations.verified badge. Verified agents become eligible for cross-user call_agent dispatch and library install.

Both default to owner and admin.

How Skills relate to Theo Agents

Skills (from theSkill Store) and Theo Agentsare two distinct surfaces that share Theo's underlying capabilities but live in their own runtimes:

  • Skillsextend Theo's chat tool surface. You install one, then mention it in chat and Theo picks the right tools automatically. Triggered by manual prompts, keywords, scheduled heartbeats, or platform events.
  • Theo Agents run as deterministic step-by-step automations — manual, scheduled, webhook, event, or Telegram-triggered. Each step calls a specific canvas skill (evi/send-email, evi/ai-summarize, etc.).

The two systems intersect through a single canvas step: Run Theo Skill (evi/run-autonomy-skill). Drop it into an agent step graph, choose a Skill Store skill by slug, and the runtime dispatches the skill mid-run with a credit-capped budget (Haiku + 3 sub-steps). Use this when you want a workflow to hand off a self-contained creative task (e.g. generate a business plan) without rebuilding the skill's prompt graph inline.

Two namespace gotchas worth knowing:

  • Different slug namespaces. Each Theo Agent step has a canvasSkillSlug like evi/research-deep — that names a canvas building block, NOT a Skill Store skill. Skill Store slugs (e.g. biz-plan-generator) only appear inside the config of a Run Theo Skill step. (The on-disk JSON wire key on `automations.steps` is still skillSlug for back-compat; the rename to canvasSkillSlug happens in-memory via the `parseSteps` / `serializeSteps` adapter.)
  • Different categories. Skills use { productivity, domain, integration, automation, creative }; Theo Agents use department categories ({ sales, support, hr, engineering, marketing, it, opencharts, starters }). The Library's category chip row is the canonical place to filter agents; the Skill Store has its own filter.

Feature manifest

The canonical surface inventory lives at .manifests/theo-agents.json. It enumerates every type, route, collection, service, test, and hard rule that belongs to Theo Agents. Update it whenever you add or remove a Theo Agents surface so the contract test in __tests__/contracts/registryVerification.test.tskeeps catching drift.

Run history

Every execution writes a row to execution_runs with the per-node status, total duration, credits used, and any error message. The run history page at /theo-agents/[id]/runs renders these for owners, and the Insights aggregator scans them when building its snapshot.

Was this article helpful?

Related Articles