camelRun by camelAI
Deploy AI
agents
and
chat apps
camelRun runs your AI agent and streams every reply into your app. One server route and one React component give each of your users an agent of their own, and your agent can answer in Slack and Telegram too.
"use client";
import { AgentChat } from "@camelai/run-react/ui";
import type { ToolRenderProps } from "@camelai/run-react";
/** A tool call rendered with your own component ("generative UI"): here, get_weather as a card. */
function WeatherCard({ args, state, result }: ToolRenderProps) {12 lines folded}
export function Chat() {
return (
<AgentChat
endpoint="/api/agent"
tools={{ get_weather: WeatherCard }}
suggestions={["What's the weather in Lisbon?", "Write a haiku about deploys", "Explain SSE in two sentences"]}
style={{ flex: 1, minHeight: 0 }}
/>
);
}npm create @camelai/run-app my-appWhat's the weather in Lisbon?
It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.
<AgentChat
endpoint="/api/agent"
tools={{ get_weather: WeatherCard }}
suggestions={["What's the weather in Lisbon?", "Write a haiku about deploys", "Explain SSE in two sentences"]}npm create @camelai/run-app my-appWhat's the weather in Lisbon?
It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.
In the browser
Your API key stays on your server
Your route gives each user's browser a token that reads only their own agent. Replies stream straight from camelRun to the browser, never through your server, and if the connection drops, the chat catches up.
import { cookies } from "next/headers";
import { createAgentHandler } from "@camelai/run/server";
import { schema, tool } from "@camelai/run";
/**
* The route the chat talks to. Your API key (CAMELAI_API_KEY) stays on this server: browsers get
* short-lived read-only tokens for their own agent, and everything they send goes through here, as
* the user `authorize` returns.
*/
export const POST = createAgentHandler({
authorize: async () => {9 lines folded},
agent: {18 lines folded},
});import { cookies } from "next/headers";
import { createAgentHandler } from "@camelai/run/server";
import { schema, tool } from "@camelai/run";
/**4 lines folded*/
export const POST = createAgentHandler({
authorize: async () => {9 lines folded},
agent: {18 lines folded},
});Explain SSE in two sentences
SSE is one HTTP response that stays open while the server writes events to it. If the connection drops, the browser reconnects with the last event id it saw and picks up from there.
What's the weather in Lisbon?
It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.
| Name | Domain | Status | Type | Time |
|---|---|---|---|---|
| agent | localhost:3000 | 200 | fetch | 86 ms |
| events?snapshot=1 | run.camelai.com | (failed)(failed) net::ERR_INTERNET_DISCONNECTED | fetch | 3.5 s |
| history?limit=50 | run.camelai.com | 200 | fetch | 61 ms |
| state | run.camelai.com | 200 | fetch | 58 ms |
| agent | localhost:3000 | 200 | fetch | 132 ms |
| events?snapshot=1 | run.camelai.com | (failed)(failed) net::ERR_INTERNET_DISCONNECTED | fetch | 0 ms |
| events?snapshot=1 | run.camelai.com | 200 | fetch | Pending |
▾ General
- Request URL
- https://run.camelai.com/v1/agents/
client_7d1e0c94a2b35f68e09c1d7a4b2e8f3c6a915d07/ events?snapshot=1 - Request Method
- GET
- Status Code
- 200 OK
▾ Request Headers
- accept
- text/event-stream
- authorization
- Bearer abt_eyJ2IjoxLCJ0ZW5hbnQiOiJ0X2I0YzE…Browser token
- last-event-id
- 1792762981000231
function WeatherCard({ args, state, result }: ToolRenderProps) {
const data = result?.data as { city: string; temperatureC: number; conditions: string } | undefined;
return (
<div style={{ border: "1px solid var(--agent-border)", borderRadius: 12, padding: "12px 16px", maxWidth: 280 }}>
<div style={{ fontSize: 13, color: "var(--agent-muted-fg)" }}>Weather · {String(args.city ?? "…")}</div>
{data ? (
<div style={{ fontSize: 28, fontWeight: 600 }}>{data.temperatureC}°C <span style={{ fontSize: 15, fontWeight: 400 }}>{data.conditions}</span></div>
) : (
<div style={{ color: "var(--agent-muted-fg)" }}>{state === "error" ? "Could not get the weather." : "Checking…"}</div>
)}
</div>
);
}In the chat
Generative UI: show tool calls as your own React components
Give the agent tools in your route and draw each call however you like. Your component gets the arguments as the model writes them, then the result.
Slack and Telegram
Your AI agent in
Slack and Telegram
Your web chat, your Slack app and your Telegram bot can all make their agents from one definition, with the same instructions and the same tools. Every Slack thread and Telegram chat gets its own agent with its own memory.
Discord servers and GitHub pull requests work the same way.
Slack AI agentTelegram AI botChannels in the docs- Name
- Agent app
- System prompt
- You are a friendly assistant in a demo app. Keep answers short. Use get_weather when asked about the weather.
- MCP servers
- app · https://agent-app.example.com/api/tools · auth: runtime
import { serveTools } from "@camelai/run/server";
const handler = serveTools(tools, { runtime: "https://run.camelai.com", tenant: process.env.CAMELAI_TENANT! });
export { handler as GET, handler as POST };Any front end
Streaming AI chat for React, Vue, Svelte and Solid
Every front end talks to the same route, and that route runs on Next.js, Hono, Cloudflare Workers, Bun, Deno or Express. Use the prebuilt React chat, or bring your own components.
/api/agent
createAgentHandler
<AgentChat endpoint="/api/agent" thread={conversationId} />export const POST = createAgentHandler({folded});FAQ
Questions about deploying AI chat apps
How should I deploy an AI streaming chat app to production?
Keep your API key on your server and run the agent outside your web requests. With camelRun, one route checks the user and gives their browser a short-lived token for their own agent, and replies stream from camelRun straight to the browser, so no reply holds a request open on your server. On serverless hosting, serve your tools over HTTPS from a route of their own with serveTools.
What is the best AI agent builder with streaming responses for real-time chat?
For a chat in your own app, camelRun is built for exactly that. Text streams in as the model writes it, tool calls show as cards or your own components, and each user's agent keeps its history between visits. You can try an agent in the camelRun console first, with no code.
How do I deploy an AI chatbot?
Set CAMELAI_API_KEY and run npm create @camelai/run-app my-app. You get a Next.js app with the chat, its route and a sample tool. Swap the demo sign-in for yours, give the agent your instructions and tools, and deploy it anywhere next start keeps running, such as a container or a Node server.
Can I deploy AI bots to Slack, Telegram and Discord?
Yes. Add a channel in the camelRun console or with POST /v1/channels, with your bot's token and the definition its agents are made from. Every Slack thread, Telegram chat and Discord channel or thread gets its own agent with its own memory.
How is this different from calling a model API directly?
A model API sends back tokens. camelRun also runs the agent loop, calls your tools, keeps each user's history, streams to the browser and reconnects when the network drops, and wakes the agent when a Slack or Telegram message arrives.
Can I keep using the Vercel AI SDK's useChat?
Yes. AgentRuntimeChatTransport from @camelai/run/ai-sdk plugs camelRun into useChat and AI Elements. The agent keeps the conversation, so only the new message is sent.
Start here
Create an AI chat app
Get an API key and run the scaffold. Your app starts with this chat, its route and a sample tool, ready to make your own.
# https://run.camelai.com/console/tokens
export CAMELAI_API_KEY=art_...
npm create @camelai/run-app my-app
cd my-app && npm run devHow can I help?
- What's the weather in Lisbon?
- Write a haiku about deploys
- Explain SSE in two sentences
Read https://run.camelai.com/SKILL.md and set up camelRun in this project. Ask me what the agent should do.
Paste into Claude Code, Codex, Cursor or any coding agent. It asks what your agent should do, then builds it.
camelRun is prepaid: $0.01 per agent-hour while an agent is in a run, $0.10 per GB-month of storage, and $0 for tokens on your own provider keys. Idle and sleeping agents cost only storage. No subscription, no seats.
- camelRuncamelRunThe hosted runtime for AI agents that keep their history and call your tools.
- camelRunSlack AI agentGive every Slack thread its own AI agent with your tools and its own memory. It asks for approval in the thread before a risky step.
- camelRunTelegram AI botPaste a BotFather token and every Telegram chat gets its own AI agent, with your tools, its own history, voice notes and photos.
- camelRunGitHub AI agentGive every GitHub issue and pull request its own AI agent. It reads the diff, uses your own tools, and replies in a comment.
- camelRunMulti-tenant AI agentsGive every user or conversation of your app its own AI agent. Each tool call says whom it is for, browsers read only their own agent, and each customer can bring its own model keys.
- camelRunDurable AI agentsAgents whose history, files and unfinished work live in camelRun, so a turn carries on through deploys and crashes without sending a tool call twice.
- camelRunVercel eve alternativecamelRun next to Vercel eve: define a durable AI agent in agent.yaml or a few lines of code, call it from Vercel, Workers, Bun, Deno, Node or Python, and connect Slack, Discord, Telegram and GitHub.
- BlogHow to deploy AI agents with persistent stateWhat a production agent runtime has to do, with a checklist.
- BlogHow to build an AI agent: 3 waysWrite the loop yourself, run a harness, or use a hosted runtime.
- DocsAdd a chat to your appThe route, the UI, tools, threads and theming.
- DocsQuickstartYour first agent in TypeScript or Python.