Public Assistants¶
This guide explains how to expose EpsimoAI assistants for public access — without requiring callers to have an EpsimoAI user account or JWT. This is essential for embedding assistants in external platforms (Typebot, Zapier, custom websites) or building public-facing chatbots.
Overview¶
Every assistant has an access mode that controls who can call it via the public endpoints. There are three modes:
| Access Mode | Auth Required | Use Case |
|---|---|---|
authenticated |
Yes (JWT) | Default. Only logged-in EpsimoAI users via /runs/stream |
public_token |
Yes (per-assistant token) | External integrations, embedded bots |
public_no_auth |
No | Public demos, VPN-protected internal tools |
Access Mode: authenticated (Default)¶
This is the default for all assistants. The assistant can only be used through the authenticated /runs/stream endpoint with a valid user JWT.
Public endpoints will reject requests with:
{
"detail": "This assistant is not configured for public access. Please use the authenticated /runs endpoints instead, or set type==agent/access_mode to 'public_token' or 'public_no_auth'."
}
Configuration¶
No action needed — this is the default. To explicitly set it:
curl -X PATCH https://backend.epsimoagents.com/assistants/<assistant-id> \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"config": {
"configurable": {
"type==agent/access_mode": "authenticated"
}
}
}'
Security Implications¶
- Safest mode. Only users with valid JWTs (scoped to the assistant's project) can interact.
- All conversations are attributed to the calling user.
Access Mode: public_token¶
The assistant is accessible via public endpoints to anyone who presents the correct token. The token acts as a per-assistant API key.
Configuration¶
Set two config values on the assistant:
curl -X PATCH https://backend.epsimoagents.com/assistants/<assistant-id> \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"config": {
"configurable": {
"type==agent/access_mode": "public_token",
"type==agent/public_token": "pubkey_mybot_abc123"
}
}
}'
Token recommendations:
- Use a prefix like pubkey_ for easy identification
- Generate a random suffix: pubkey_$(openssl rand -hex 16)
- Store it securely — anyone with this token can use your assistant (and your LLM credits)
How to Pass the Token¶
The token can be provided in three ways (checked in this order):
Authorization: Bearer <token>header — compatible with OpenAI SDKs and TypebotX-Public-Bot-Token: <token>header — EpsimoAI-specific headertokenfield in the JSON body — for the/public/runs/streamendpoint
Security Implications¶
- Anyone with the token can call the assistant — no user identity is tracked.
- All conversations are attributed to the assistant's
project_id(not a specific user). - No built-in rate limiting — a leaked token means unlimited usage on your LLM credits.
- Rotation: Change the
public_tokenvalue in the assistant config. Old tokens stop working immediately.
Access Mode: public_no_auth¶
The assistant is fully open — no token or authentication of any kind is required.
Configuration¶
curl -X PATCH https://backend.epsimoagents.com/assistants/<assistant-id> \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"config": {
"configurable": {
"type==agent/access_mode": "public_no_auth"
}
}
}'
Security Implications¶
- Maximum exposure. Anyone who discovers the assistant ID can use it.
- No rate limiting — potential for abuse and runaway LLM costs.
- Suitable only for:
- Public demos with expendable budgets
- Internal tools behind a VPN or firewall
- Prototyping and testing
Public Endpoints¶
/public/runs/stream — Native Streaming Endpoint¶
The EpsimoAI-native endpoint for public assistant interaction. Returns Server-Sent Events (SSE).
Request Format¶
curl -N https://backend.epsimoagents.com/public/runs/stream \
-H "X-Public-Bot-Token: pubkey_mybot_abc123" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "<assistant-id>",
"thread_id": "session-12345",
"input": [{"role": "human", "content": "Hello!"}]
}'
Request Body Fields¶
| Field | Type | Required | Description |
|---|---|---|---|
assistant_id |
string | Yes | The assistant's UUID |
thread_id |
string | Yes | A stable session identifier. Maintains conversation state. |
input |
array or object | No | Messages to send. Array of message objects or a state dict. |
config |
object | No | Optional per-call configuration overrides |
token |
string | No | Alternative to the X-Public-Bot-Token header |
Input Formats¶
Array of messages (most common):
{
"input": [
{"role": "human", "content": "What's the weather like?"}
]
}
State dictionary:
{
"input": {
"messages": [
{"role": "human", "content": "What's the weather like?"}
]
}
}
Response Format (SSE)¶
The response is a stream of Server-Sent Events:
event: metadata
data: {"run_id": "..."}
event: messages/partial
data: [{"type": "ai", "content": "Hello! "}]
event: messages/partial
data: [{"type": "ai", "content": "Hello! How can I help?"}]
event: end
data: {}
Each messages/partial event contains the full accumulated message content up to that point (not just the delta).
/public/openai/v1/chat/completions — OpenAI-Compatible Endpoint¶
Mimics the OpenAI API format. See the full OpenAI-Compatible Endpoint guide for details.
curl https://backend.epsimoagents.com/public/openai/v1/chat/completions \
-H "Authorization: Bearer pubkey_mybot_abc123" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": false
}'
Key difference from /public/runs/stream: the token alone identifies the assistant (no assistant_id field needed).
The X-Public-Bot-Token Header¶
EpsimoAI's custom header for passing the public access token. An alternative to Authorization: Bearer.
When to use it:
- When calling /public/runs/stream directly
- When the Authorization header is already used for something else
- When you prefer explicit separation from JWT-based auth
curl -N https://backend.epsimoagents.com/public/runs/stream \
-H "X-Public-Bot-Token: pubkey_mybot_abc123" \
-H "Content-Type: application/json" \
-d '{
"assistant_id": "abc-123-def",
"thread_id": "my-session",
"input": [{"role": "human", "content": "Hi"}]
}'
Thread/Session Management¶
For public assistants, the thread_id in the request body serves as the session identifier:
- Same
thread_id= continues the same conversation (messages accumulate) - New
thread_id= starts a fresh conversation
The thread is created automatically on first use — no separate "create thread" call is needed for public endpoints.
Best practices:
- Use your platform's session ID as the thread_id (e.g., Typebot's sessionId)
- For anonymous web widgets, generate a UUID per browser session and store it in localStorage
- Thread IDs are strings — any format works (UUIDs, slugs, hashes)
Comparison of Public Endpoints¶
| Feature | /public/runs/stream |
/public/openai/v1/chat/completions |
|---|---|---|
| Format | EpsimoAI native (SSE) | OpenAI-compatible JSON/SSE |
| Assistant identification | assistant_id in body |
Token lookup (no ID needed) |
| Token header | X-Public-Bot-Token |
Authorization: Bearer |
| Thread management | Explicit thread_id |
Managed internally per token |
| Streaming | Always SSE | Optional (stream: true/false) |
| Best for | Custom integrations | OpenAI SDK, Typebot, no-code tools |
Security Best Practices¶
- Prefer
public_tokenoverpublic_no_authunless you have network-level controls. - Rotate tokens regularly — especially if you suspect a leak.
- Monitor usage — watch your LLM provider's billing dashboard for unexpected spikes.
- Use descriptive token prefixes — makes it easy to identify which assistant a leaked token belongs to.
- Set up billing alerts on your LLM provider (OpenAI, Anthropic, etc.) as a safety net.
- Consider a reverse proxy with rate limiting (e.g., AWS WAF, Cloudflare) in front of public endpoints for production deployments.
Related Documentation¶
- Authentication Guide — Full auth reference including public tokens
- OpenAI-Compatible Endpoint — Detailed guide for the OpenAI-format endpoint
- API Reference — Full endpoint documentation
- CLI Recipes — Bash automation examples