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.

my-app/app/components/chat.tsx
"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-app
agent-app.example.comAgent asleep
Agent app

What's the weather in Lisbon?

Weather · Lisbon
29°C Windy

It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.

Message the agent…
my-app/app/components/chat.tsx
    <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-app
agent-app.example.comAgent asleep
Agent app

What's the weather in Lisbon?

Weather · Lisbon
29°C Windy

It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.

Message the agent…

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.

How browser tokens work
my-app/app/api/agent/route.ts
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},
});
localhost:3000
Agent app

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?

Weather · Lisbon
29°C Windy

It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.

Message the agent…
Requests the chat makes
NameStatusTime
agent20086 ms
events?snapshot=1(failed)(failed) net::ERR_INTERNET_DISCONNECTED3.5 s
history?limit=5020061 ms
state20058 ms
agent200132 ms
events?snapshot=1(failed)(failed) net::ERR_INTERNET_DISCONNECTED0 ms
events?snapshot=1200Pending

▾ 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
Browser
Agent on camelRun
my-app/app/components/chat.tsx
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.

Add a chat to your app
  1. state input_streamingstate: "input_streaming"Model writes args
    Weather · Lis
    Checking…

    args { city: "Lis" }

    chat.tsx:11<div style={{ fontSize: 13, color: "var(--agent-muted-fg)" }}>Weather · {String(args.city ?? "…")}</div>
  2. state runningstate: "running"Your tool runs
    Weather · Lisbon
    Checking…

    get_weather({ city: "Lisbon" })

    chat.tsx:15<div style={{ color: "var(--agent-muted-fg)" }}>{state === "error" ? "Could not get the weather." : "Checking…"}</div>
  3. state donestate: "done"Result
    Weather · Lisbon
    29°C Windy

    result.data { city: "Lisbon", temperatureC: 29, conditions: "Windy" }

    chat.tsx:13<div style={{ fontSize: 28, fontWeight: 600 }}>{data.temperatureC}°C <span style={{ fontSize: 15, fontWeight: 400 }}>{data.conditions}</span></div>

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
agent-app.example.comasleep
Agent app

What's the weather in Lisbon?

Weather · Lisbon
29°C Windy

It's 29°C and windy in Lisbon right now. Warm, with a strong breeze by the river.

Message the agent…

Thread# trips

Jonas Weber 9:41 AM

@Agent app what's the weather in Berlin?

1 reply

Agent appAPP9:41 AM

It's 18°C and sunny in Berlin right now.

Reply…

Agent app

typing…

What's the weather in London?9:42 ✓✓

It's 10°C and raining in London right now. Bring an umbrella.9:42

Message
Definitiondef_…
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.

Front ends
Your route

/api/agent

createAgentHandler

Runs on
camelRun
React<AgentChat endpoint="/api/agent" thread={conversationId} />
Next.jsapp/api/agent/route.tsexport 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.

Terminal
# https://run.camelai.com/console/tokens
export CAMELAI_API_KEY=art_...
npm create @camelai/run-app my-app
cd my-app && npm run dev
localhost:3000Agent asleep
Agent app

How can I help?

  • What's the weather in Lisbon?
  • Write a haiku about deploys
  • Explain SSE in two sentences
Message the agent…
Set up with your coding agent

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.