Agents
End user sessions
Use end user sessions to let the people using your product talk to an agent directly from their own browser or mobile app. The end user's own credential creates, runs, and reads their own conversations, so your backend does not have to proxy every message, and the platform enforces that no end user can ever see another end user's sessions.
End users always reach an agent through an alias, never through an agent key. The alias is the public name you hand to your client; behind it you can re-route, split, or replace agents without changing anything the client calls.
Two ways to expose a session
Vectara agents expose sessions through two different surfaces, for two different callers.
Operator sessions (/v2/agents/{agent_key}/sessions) | End user sessions (/v2/agent_aliases/{alias_key}/end_user_sessions) | |
|---|---|---|
| Caller | Your backend, holding an API key | The person chatting with the agent |
| Visibility | Every event, including tool traces and reasoning | The session's messages, the client tool calls it waits on, and the output types its widget connector reveals |
| Ownership | Can act across any of your customer's sessions | Locked to the caller's own identity |
| Credential | API key or application client | A platform user holding agent_end_user, an anonymous widget visitor (an X-Visitor-Id minted through POST /v2/visitors), or a federated end user (a token from your own identity provider) |
If your backend already mediates every message (for example, to inject session metadata for per-user access control), operator sessions are still the right surface. Reach for end user sessions when you want to hand the session credential directly to an untrusted client, such as a browser tab or a mobile app, and skip building your own proxy.
What end user sessions guarantee
A caller can only ever reach their own sessions
There is no parameter anywhere in this API for choosing whose sessions to
read. The owning principal is stamped from the caller's authenticated
identity when the session is created, and it can't be set or changed
afterward. Listing sessions returns only the caller's own, and getting,
sending to, or deleting a session owned by someone else returns 403, never
that other person's data.
This isolates your end users from each other, not from you. An end user session is a regular agent session underneath, so it still appears in your own session list and in the Console, where your team can read it, inspect its full event history, and delete it. Plan for that when deciding what your end users are invited to type into a conversation.
End users see messages, and only what you reveal
The full agent event stream includes internal detail — reasoning traces, tool calls, step transitions, compaction — that isn't meant for an end user. End user sessions always expose these event types:
input_message— what the end user said.agent_output— what the agent replied.error— a turn-ending failure signal, carrying a generic message that does not identify the underlying cause. Without it, a failed turn would be indistinguishable from one that simply produced no reply.client_tool_pending— the client tool calls the agent waits on the end user to answer. See Answer client tool calls.tool_inputandtool_outputof client tools — each client tool call and the output the end user submitted for it.
A widget connector can also reveal the calls of every other tool, reasoning,
and structured output through its revealed_output_types. Every other event type is
invisible to an end user. New event types are invisible by construction, so
an agent that starts using one cannot start leaking it.
Grant a user access
An end user is any principal holding the agent_end_user role, scoped to one
specific alias key. This role grants nothing else. A
user account is the usual holder, but an API key, an application client, an
anonymous widget visitor, or a federated end user may hold it too: each owns
the sessions it creates and reaches no one else's. The other agent roles reach
these operations as well, and an agent administrator is bound to its own
sessions the same way; the operator endpoints under
/v2/agents/{agent_key}/sessions remain the administrative view of an
alias's sessions.
The role must name an alias. Granting it on an agent key is rejected — publish the agent behind an alias and grant on that alias key instead.
The role grants the end-user session operations of the alias it names and
nothing else — not reading users, not creating API keys, not querying corpora.
That is what makes the credential safe to hand to an untrusted client: adding
agent_end_user to an account never widens what that account can reach.
You can hold it alongside other roles, which is useful for testing your own published agent from a developer account. Bear in mind that such an account still has everything its other roles grant, so for a credential you intend to ship to a browser or mobile app, give the end user their own account rather than adding the role to a teammate's existing one.
Grant access (Console)
- Log into the Vectara Console.
- Navigate to the Team page.
- Select the user you want to grant access to.
- Open the Agents access tab.
- Click Grant access to agent, choose the alias, select Agent end user, and click Grant access.
Grant access (API)
Send a PATCH request to the user's endpoint with the role scoped to your
alias's key.
Grant the agent_end_user role
Code example with multiple language options.1
See Update user for the full request shape. The
agent_key field carries the alias key here; agent keys and alias keys are
separate namespaces for a customer.
Create a session and chat
Once a user holds the role, they authenticate as themselves and call the dedicated end user endpoints with their own credential.
Create a session
Code example with multiple language options.1
Every end user session binds to the widget connector named by the required
connector_id, which is what carries its settings (its idle lifetime, the
event types it reveals, and the session_metadata written under
metadata.connector.<connector_id> of each of its sessions, which the agent
reads as session.metadata.connector.*). The named connector must be an
enabled widget connector created on the addressed alias, or the request is
rejected with 400. name and description are optional; if you omit
them, the server names the session for you and fills in a description once
the agent has produced a response.
The alias resolves which agent handles the session once, at creation time. If you later shift the alias's routing, sessions created before the shift keep running on the agent they started with, and your client keeps calling the same alias URL throughout.
Send a message
Code example with multiple language options.1
The response contains that turn's visible events. Sending a message while the
session is already processing one returns 409. To attach files to a
message, send the same request as multipart form data with one or more
files parts.
Stream the response
Set stream_response to true on the same request to receive the reply as
Server-Sent Events. Live text arrives incrementally as streaming_agent_output
chunks, followed by the complete, persisted agent_output event.
Streaming response
Code example with bash syntax.1
Answer client tool calls
A client tool (type: client) is a tool that the client runs instead of the
platform. When the agent calls one in an end user session, the response ends with a
client_tool_pending event, and the session waits until the end user's client
submits the call's output. Use client tools to show the end user something the
agent produces, such as a form, and to bring back what the end user enters.
Each entry in pending_calls carries the event_id of the call, the
tool_name, and the arguments to run the tool with. The arguments include
any values that the tool configuration's argument overrides resolve, with
secret values unmasked. In a widget session the client is the visitor's
browser, so do not override a client tool's arguments with a secret or any
other value that the end user must not see.
The client_tool_pending event is not saved with the session's history. A
client that reconnects or reloads reads the calls the session is waiting on
from GET /v2/agent_aliases/{alias_key}/end_user_sessions/{session_key}/outstanding_client_tool_calls.
The history keeps each client tool call as a tool_input event and the
submitted output as a tool_output event with the same tool_call_id, so a
client can show the forms an end user already answered. These events carry
the arguments the agent wrote, without the values of the tool configuration's
argument overrides.
To answer, submit a tool_output input with one entry for each pending call.
An entry is either a success with the tool's output, or an error that
tells the agent why the call failed. When the client tool defines an
output_schema, an output that does not match it is rejected with 400.
Submit a client tool output
Code example with json syntax.1
The agent then continues the turn with the output, and the response contains
the turn's visible events. A client that cannot run a tool should answer with
an error entry, because the session cannot continue until every pending call
has an output.
Limits
Each end-user principal has a per-customer cap on live sessions and on
sessions created per hour. Exceeding either returns 429. Delete a session
to free up capacity within the live-session cap; the hourly cap resets on a
rolling basis.
A session's idle lifetime is not something the end user sets. It comes from
the widget connector the session binds to: the widget's session_tti_minutes
is applied to every session created through its alias, and the session is
deleted automatically after that long without activity. The effective value is
reported back as tti_minutes on the session object.
Restricting widget origins
Set configuration.allowed_origins on a widget connector to restrict browser access:
{
"configuration": {
"type": "widget",
"allowed_origins": ["https://example.com", "https://*.example.com"]
}
}
Use up to 20 unique lowercase HTTPS origins, each at most 255 characters, without ports, paths, or trailing slashes. Wildcards match subdomains at any depth, excluding the apex and origins with ports.
On create, omitted or [] allows any origin. On update, omitted preserves the
list; null or [] clears it. Null entries are rejected.
With a non-empty list, unmatched Origin headers receive 403 on the public
connector view and session creation, reads, deletion, events, and inputs. This
applies to anonymous and signed-in callers. Visitor minting and session listing
are exempt.
Existing sessions pick up changes within a few seconds. Disabling or deleting the connector stops origin checks; other admission and ownership checks still apply.
Requests without Origin are allowed, so this setting does not restrict non-browser
clients.
Next steps
- Build an embedded agent with a widget connector - a worked anonymous-widget example, not a sign-in integration.
- Agent aliases - the public name end users call, and how to route it to different agents.
- Sessions - the operator-facing session surface, and how to pass per-user identity through session metadata.
- Agent End User Sessions API reference - full request and response schemas for every operation.