AI Agents
An AI Agent is a reusable, configured object - like a template - that reads a bounded context and emits validated structured output. That output is then used by the surrounding journey or catalog job; the agent itself never sends, branches, updates an attribute, or calls an API.
Find them under Settings → AI Agents. Building and editing agents needs the settings:write role scope (or an API key with ai_agents:write); viewing needs settings:read / ai_agents:read.
Generate-only: decide, don't act
This is the core idea, and it is deliberate. An AI Agent is not an autonomous tool-calling bot. It has no tools and no actions. On each run it:
- Reads only the context you opted it into (selected attributes, segments, catalog fields, brand voice, recent engagement).
- Asks the model to produce output that matches a strict output schema you defined.
- Validates that output and returns it - plus an optional
explanationof the model's reasoning.
Everything that acts on the result already exists in Joryio: your journey sends the message, takes the branch, or writes the attribute; your catalog enrichment job writes the value into a field. The agent only supplies the generated value. This keeps the powerful, side-effecting machinery under the guardrails you already trust (sending caps, suppression, branching) and keeps the AI scoped to what it is good at - generating and deciding.
Creating an agent
Instructions
The instructions are the agent's goal - its system prompt. They are Liquid-templated with your workspace vocabulary and the selected context at run time, so you can reference real attribute and event names. Describe what you want generated and the rules it must follow (tone, length, allowed values).
The model only sees the context fields you list under Context selectors. If your instructions mention a field name (e.g. "check the price") but that field isn't in the context, the model can't act on it. Name the exact field you exposed - e.g. "if series_id is greater than 1200…". The run history shows the exact input the model saw, which makes this easy to spot.
Tags
Give an agent tags to organize and filter your agent library. Tags come from your shared workspace tag pool (the same tags you use on campaigns, journeys, and templates), so they autocomplete as you type and you can filter the agent list by tag. Tags are counted in the Tags management UI like any other tagged resource.
Model: managed vs. BYO
Every agent runs on one model, configured two ways:
- Managed - Joryio Auto. One option: Joryio automatically selects the best hosted model (and its reasoning effort) for each run. There is nothing to tune - no model id, no thinking level. You pay the token cost plus our markup, billed as one credit per run from your wallet. No key setup; it just works.
- BYO (bring your own) - your own provider key. Supported providers: Anthropic, OpenAI, Google (Gemini), Azure OpenAI, and AWS Bedrock. Here you specify the concrete model id to call (for example
claude-opus-4-8,gpt-4o,gemini-1.5-pro). You pay your LLM provider directly for tokens; Joryio takes a small flat platform fee per run. Add the key under Provider Keys (see below) before selecting BYO.
Context selectors (what the agent may read)
Context is opt-in. An agent reads nothing about a contact or record unless you list it here:
- Attribute keys - the contact attributes to include.
- Segment memberships - flags for the segments you list.
- Catalog fields - fields from the catalog or entity record being enriched.
- Required fields - a subset of catalog fields that must be present for the agent to run. During enrichment, any row missing one of these is skipped and never billed (the skip reason is recorded). Enriching an incomplete row wastes a run and usually produces a worse answer, so require the fields the agent genuinely needs.
- Brand voice - include your workspace brand voice so the output sounds on-brand.
- Recent engagement - a short summary of the contact's recent activity.
- PII masking - PII is managed globally: mark an attribute as PII under Custom Attributes and it's automatically redacted before the model sees it, in every agent.
Output schema
The output schema constrains what the model may return, so downstream nodes always get a predictable shape:
- Type -
string,number,boolean, orjson. - For
json, a list of named fields, each with a primitive type (string,number,boolean) and an optional description. - Include explanation - capture the model's reasoning in an
explanationfield (a cheap, inspectable trace).
Output that does not match the schema is rejected and treated as a failure (see the error contract below).
Fallback value
Every agent has a fallback value - the value substituted whenever a run fails for any reason. This guarantees your journey never stalls waiting on the model: on failure it either takes the wired error edge or continues with the fallback.
Daily cap
Each agent has its own daily run limit (default 250,000; 0 = unlimited) - the maximum times that agent runs per day. Once reached, further runs fail-closed with a budget_exceeded outcome (and take the fallback / error edge), protecting your spend from a runaway journey. Your account also has a workspace-wide daily cap across all agents combined, managed by Joryio - contact us to raise it.
Guardrails
Runtime guardrails per run: a hard timeout (default 20 s), an optional max output tokens limit, and whether to retry on transient errors (rate limits and 5xx only - never on a bad key or invalid output).
Create an agent from the AI assistant
You can also have the Joryio Assistant build an agent for you: describe what you want (for example, "an agent that reads a product's price and writes high or low") and it proposes a ready-to-apply agent. It shows an Apply card summarizing the agent; nothing is created until you press Apply. On Apply, the agent is created as a draft and you get a link to open it in the editor - so you always review, test, and activate it yourself before it runs. Assistant-created agents are always Managed (Joryio Auto); the assistant never selects a BYO provider or handles keys.
Using an agent in a journey
Drop an AI Agent node into a journey and pick the agent. For each contact, the node reads the context, runs the agent, and writes the output into the execution snapshot so later nodes (messages, branches, attribute updates) can reference it.
The node exposes first-class outcome edges so you can branch on how the run went:
success- the model returned valid output; that output is available downstream.fallback- a run failed but you did not wire a specific error edge; the fallback value is used and the journey continues.erroroutcomes -timeout,rate_limited,invalid_config, andbudget_exceeded. Each is a separate branch edge on the node, so you can wire every error outcome to its own distinct path in the canvas (or leave any of them to fall through tofallback).
This explicit error contract is a deliberate differentiator: rather than silently failing to a null and forcing you to defend every downstream node, an AI Agent lets you route "the agent errored → take this branch" like any other decision.
Catalog enrichment
An agent can also run over your catalog or custom-entity records to generate or categorize a field - product descriptions, tags, a next-best-item, a normalized category. You choose the agent, the entity, the target field the output is written into, and an optional filter to narrow which records are processed. Each row's run is metered and traced exactly like a journey run.
The enrichment job runs asynchronously in the background: you submit a job and it returns immediately with a queued job id, so a large catalog (up to 100k rows) processes off the request path instead of blocking. You then poll the job for its status and counts - the status moves through queued → running → completed (or failed), and the counts (total, processed, succeeded, failed, skipped) fill in as it goes. The job is idempotent per record, so a re-run never re-charges an already-enriched row. You can trigger it and watch progress from the dashboard, or via the enrichment endpoints.
Only successful runs write the field. A row is skipped (its existing value left untouched) whenever the agent returns a non-success outcome - a missing required field, an empty wallet (budget_exceeded), a misconfigured BYO key (invalid_config), and so on. When any rows are skipped, the job surfaces a reason (for example "2 of 2 rows not written - invalid_config: …") so you know why nothing was written, instead of just a bare count. Catalog enrichment is billed per run; Test and preview are free (see below).
Testing and preview
Before you deploy an agent, use Test to dry-run it against a sample context you supply (sample attributes, segment memberships, a catalog record, an engagement summary). The preview returns exactly what a real run would produce:
outcome-success,fallback, or one of the error outcomes.output- the validated structured output (or the fallback on failure).explanation- the model's reasoning, when your schema includes it.
Test and preview runs use a fresh run key, never count against a real journey, and are free - no wallet balance is required - so you can iterate on an agent (and a funded wallet is only needed for real journey/catalog runs). If a test reports a non-success outcome, the exact error reason is shown so you can fix it (a missing key, an unfunded wallet, output that failed schema validation, and so on).
The error contract
Every run ends in exactly one outcome:
| Outcome | Meaning | Retried? |
|---|---|---|
success | Valid output matching the schema. | - |
fallback | A run failed and no specific error edge was wired; the fallback value is used. | - |
timeout | The run exceeded the per-run timeout. | Transient - retried if enabled. |
rate_limited | The provider rate-limited the request. | Transient - retried if enabled. |
invalid_config | Deterministic failure: bad/expired key, a pricing/debit configuration error, or the model produced output that fails schema validation. | No - never retried. |
budget_exceeded | A spend limit was hit: the agent's daily run limit, the account's workspace-wide daily cap, or an insufficient wallet balance for a billed run. | No. |
Retries use bounded exponential backoff and only ever apply to transient failures.
Metering and cost
Runs are metered per invocation:
- Managed - 1 credit per run, debited from your wallet. The credit is priced with token headroom plus our markup.
- BYO - a small flat platform fee per run; you pay your own provider for the tokens directly.
Free AI credit. Every account gets a monthly pool of free AI credit (default $5/month) that only AI-agent runs may spend - it's separate from your messaging wallet, so SMS/WhatsApp/email never draw it down. Each run spends free credit first, then falls back to your paid wallet once the credit is used up. The credit resets at the start of each month (use-it-or-lose-it) and its balance is shown on Settings → Usage. Test and preview runs are always free regardless of credit.
Debits are idempotent by run id, so a retried journey step is never double-charged. Token counts and internal cost are tracked on each run for your usage reporting.
Spend limits. Each agent has its own daily run limit, and your account has an account-wide daily AI-run cap across all agents and workspaces. Both the free-credit amount and the account cap can be tuned per account by Joryio - contact us if you need more headroom.
Run history
Every run is recorded and browsable on the agent's own Run history screen - open it from the Runs button on the agent in the list (it's a dedicated page, not buried in the config editor). Each run is expandable and shows:
- the outcome, any error reason, latency, and cost;
- the input the model saw - the exact prompt (system instructions + the selected, already-masked context);
- the output it returned and the optional explanation.
Seeing the real input next to the output is the fastest way to debug and improve an agent: if the answer is wrong, the input usually tells you why (for example, the instruction referenced a field you didn't expose). You can also fetch runs via the runs endpoint.
Data governance
- PII is opt-in. An agent only sees the attributes, segments, and fields you explicitly select. Nothing about a contact reaches the model by default.
- Global PII masking. Mark an attribute as PII once under Custom Attributes and it's automatically redacted before the context reaches the model, in every agent - you don't re-select it per agent.
- Input is stored masked, for inspection. So you can debug and improve agents, each run stores the prompt the model saw (system + context) - after PII masking and bounded in size. It never contains values you've marked as PII. This powers the Run history above.
- Workspace isolation. An agent can only read the workspace it runs in, and BYO keys live in a per-workspace encrypted vault - their secret values are never returned by the API.
Next steps
- AI Agents API - manage agents, provider keys, and runs over REST.
- Canvas (Journey Builder) - where the AI Agent node lives.
- Brand Voice & AI Writing - the brand voice an agent can read.
- Usage & Billing - the wallet that per-run credits are debited from.