Alias workflows and best practices
An alias puts a stable name in front of your agents and lets a policy decide which agent owns each new session. That indirection is what makes it safe to change agents while they are in production. This guide is the operator's playbook for that: how to roll out new versions, run experiments, route cohorts, and keep things tidy as the number of agents grows.
If you are new to aliases, read Agent aliases for the routing model first, and Route sessions with an alias for the step-by-step API calls. This page assumes both and focuses on the workflows you build on top of them.
Every example applies the same way from the API or the Console. In the Console, open Aliases, select an alias, and use Replace policy to apply any of the policies below.
Treat agent versions like deploys
The core habit: never improve an agent in place while it serves traffic. Build the new version alongside the old one and shift traffic to it deliberately, exactly as you would roll out a backend service.
An alias makes this cheap. Callers integrate against the alias key once, and from then on which agent answers is a server-side routing decision. A spare agent costs you nothing, so keep one around to experiment in, and promote it only when you are ready.
Pattern 1: Roll out a new agent version
This is the workflow aliases are built for: clone, canary, ramp, promote, retire.
Establish the handle
Put your current agent behind an alias whose policy is a single catch-all rule. Behavior is identical to calling the agent directly, but callers now address the alias.
{
"type": "routed",
"rules": [
{ "targets": { "type": "single", "agent_key": "support-v1" } }
]
}
Point your callers at support. This is the last integration change they make.
Clone and experiment
Copy support-v1 to a new agent, support-v2, and change whatever you want on
the copy: the system prompt, the model, the tools. No production traffic reaches
it, so there is nothing to be careful about. Test it directly with
POST /v2/agents/support-v2/sessions until you are happy.
Canary a slice of traffic
Replace the alias policy with a weighted target that sends a small share to the new version. Partition the split by a stable identifier so a given customer stays on one version while you evaluate. See Choosing how a weighted split assigns sessions.
{
"type": "routed",
"rules": [
{
"targets": {
"type": "weighted",
"partition_by": "get('$.session.metadata.account_id', '')",
"options": [
{ "agent_key": "support-v1", "weight": 90 },
{ "agent_key": "support-v2", "weight": 10 }
]
}
}
]
}
Roughly 10 percent of accounts now resolve to support-v2, and each of those
accounts stays there across its sessions. Watch that cohort in your traces before
widening it.
Ramp
When the canary looks good, replace the policy again with new weights, for
example 50/50, then 0/100. Each step is a policy change, not a deploy.
Sessions already created keep the agent they resolved to. Only new sessions use
the updated weights.
Promote
Once support-v2 carries everything, set the policy back to a single target so
the intent is explicit and the split machinery is gone.
{
"type": "routed",
"rules": [
{ "targets": { "type": "single", "agent_key": "support-v2" } }
]
}
Retire the old agent
Before deleting support-v1, confirm nothing still routes to it. List the
aliases that point at it with the aliased_agent_key filter.
curl "https://api.vectara.io/v2/agent_aliases?aliased_agent_key=support-v1" \
-H "x-api-key: $VECTARA_API_KEY"
In the Console, open the agent and check the Aliases pointing at this agent section, which lists the same thing. An agent that is still referenced by an alias cannot be deleted until the reference is removed, so clear any stragglers first, then delete the agent.
Roll back
A bad canary is one policy change away from being undone. Replace the policy to send everything back to the previous version.
{
"type": "routed",
"rules": [
{ "targets": { "type": "single", "agent_key": "support-v1" } }
]
}
Rollback is instant and applies to every new session immediately. No redeploy, and callers never notice.
Rollback only affects sessions created after the change. A session that already
resolved to support-v2 keeps running on support-v2 until it ends. Long-lived
sessions drain on the version they started on.
Pattern 2: A/B test two versions
A canary that you hold steady is an A/B test. Split traffic by a stable identifier, keep the weights fixed for the length of the experiment, and you have two cohorts each getting one version consistently.
{
"type": "routed",
"rules": [
{
"targets": {
"type": "weighted",
"partition_by": "get('$.session.metadata.account_id', '')",
"options": [
{ "agent_key": "support-v1", "weight": 50 },
{ "agent_key": "support-v2", "weight": 50 }
]
}
}
]
}
Because assignment is a deterministic hash of partition_by, an account stays in
its group for the whole experiment. Compare the two groups on whatever you
measure: resolution rate, latency, cost, thumbs-up.
Changing the weights shifts the bucket boundaries, which moves some accounts to the other version. Do not adjust weights mid-experiment if you need clean cohorts. Set them once, measure, then promote the winner to a single target.
Pattern 3: Route cohorts to purpose-built agents
Weighted splits divide traffic by volume. match rules divide it by who is
asking. A rule's match is a UserFn boolean expression evaluated against the
session, and the first matching rule wins. Route enterprise tenants to a stronger
agent and everyone else to the default:
{
"type": "routed",
"rules": [
{
"match": "get('$.session.metadata.plan') == 'enterprise'",
"targets": { "type": "single", "agent_key": "support-enterprise" }
},
{
"targets": { "type": "single", "agent_key": "support-v1" }
}
]
}
The same shape routes by region, language, or any attribute you send in
session.metadata. A few rules of thumb:
- Always end with a catch-all. The last rule has no
match, so no session falls through to nothing. A policy where a session matches no rule is rejected. - Order matters. Rules evaluate top to bottom. Put the most specific rules first. A rule placed after a catch-all is unreachable and rejected.
- Combine patterns. Each rule's target is independent, so you can canary a
new version inside one cohort while routing the others directly. For example,
make the enterprise rule a weighted split of
support-enterprise-v1andsupport-enterprise-v2while the default rule stays a single target.
For the expression syntax, including operators and the routing context available
to match, see the UserFn language reference
and the context table in Agent aliases.
Pattern 4: Environments and safe changes
A moving target for internal builds
Keep a latest alias pointed at whatever is newest and let internal tools and
staging ride it, while the customer-facing alias stays pinned to a blessed
version. Your team always exercises the newest agent without exposing customers
to it.
One alias per environment
Give each environment its own alias, for example support-staging and
support-prod, each with its own policy. Promoting a version to production is
then a policy change on support-prod, decoupled from what staging is testing.
The kill switch
Every alias has an enabled flag. Disable an alias to stop it accepting new
sessions without deleting it or touching its policy. This is the clean way to
take a route out of service temporarily. Re-enable it to resume. In the Console,
open the alias, click Edit settings, and toggle Enabled.
Choosing how a weighted split assigns sessions
A weighted target must decide, per session, which option to use. partition_by
is the value it hashes to make that call. You have two honest choices.
partition_by | Behavior | Use when |
|---|---|---|
get('$.session.key') | Every session is bucketed independently. | Traffic is stateless or one-shot and callers have no identity you care about keeping consistent. |
get('$.session.metadata.<field>', '') | Every session sharing the same value resolves to the same option. | You want a caller (account, user, tenant) to stay on one version across sessions. This is the usual choice. |
For most products the sticky option is what you want. A 10 percent canary should mean 10 percent of your customers are on the new version and stay there, not that every customer flips between versions from one session to the next.
Two constraints to keep in mind:
- Send the field, or default it.
partition_bymust not evaluate tonull, or the session is rejected. Wrap optional fields with a default, for exampleget('$.session.metadata.account_id', ''), and make sure your callers actually send the field when they create the session. - Use a plain field name. The field is read with dotted-path notation, so the
metadata key must be a simple identifier such as
account_idortenant. Names with hyphens, dots, or spaces are not supported as partition fields.
Operating aliases as they grow
Find what routes to an agent
Before you delete or heavily change an agent, find the aliases that depend on it.
curl "https://api.vectara.io/v2/agent_aliases?aliased_agent_key=support-v2" \
-H "x-api-key: $VECTARA_API_KEY"
The Console shows the same list in the Aliases pointing at this agent section on the agent's page. This is your safety check against pulling an agent out from under a live alias.
Name for the role, not the version
Give the alias a role name that never changes (support, sales-assistant) and
give agents version names behind it (support-v1, support-v2). Callers bind to
the stable role. The versions churn behind it. Avoid encoding a version into the
alias key, since the whole point is that the alias outlives any single agent.
Prefer disable over delete for routes
If you need to stop a route, disable the alias rather than deleting it. Deleting an alias frees its key and loses its policy. Disabling keeps both and is reversible, which is what you usually want for a temporary stop.
Anti-patterns
| Anti-pattern | Why it hurts | Do instead |
|---|---|---|
| No catch-all rule | A session that matches no rule is rejected with 400. | Always end the policy with a rule that has no match. |
| A rule after the catch-all | It can never run and the policy is rejected as unreachable. | Put the catch-all last and specific rules first. |
| Per-session split for identified callers | The same customer bounces between versions across sessions. | Partition by a stable value like account_id. |
| Adjusting weights during an experiment | Changing the weights shifts the bucket boundaries, so some accounts move to the other version and muddy your A/B result. | Fix the weights, measure, then promote. |
| Version baked into the alias key | Defeats the stable-handle purpose and forces caller changes later. | Name the alias for its role, version the agents behind it. |
| Editing the live agent in place | You are changing production with no version to fall back to. | Clone, canary behind the alias, then promote. |