This tutorial maps Talon’s three client surfaces to concrete code paths in this repository.
Before you run the examples, clone the repository and create .env:
git clone https://github.com/impalasys/talon.git
cd talon
cp .env.example .env
Set OPENAI_API_KEY in .env, then start the local stack:
docker compose up --build -d
Choose the right surface
Use:
- gRPC when you want a typed backend or integration service
- REST when you want straightforward CRUD with
curlor ordinary HTTP clients - the UI session surface when you want a browser chat client like Sightline
Option 1: typed client with Connect
The UI end-to-end tests already create namespaces, agents, and sessions through the gateway. The working example lives in ui/e2e/chat.spec.ts.
The core flow is:
import { createClient } from "@connectrpc/connect";
import { createGrpcWebTransport } from "@connectrpc/connect-web";
import { GatewayService } from "../proto/proto/gateway_pb";
const client = createClient(
GatewayService,
createGrpcWebTransport({ baseUrl: "http://127.0.0.1:18789" }),
);
await client.createNamespace({ name: "client-demo", recursive: true });
await client.createAgent({
ns: "client-demo",
name: "docs-agent",
definition: {
source: {
case: "customSpec",
value: {
systemPrompt: "Answer from the tutorial client.",
modelPolicy: {
profiles: [
{
name: "default",
model: { provider: "openai", name: "gpt-5.4-nano", temperature: 0.0 },
},
],
},
},
},
},
});
const session = await client.createSession({ ns: "client-demo", agent: "docs-agent" });
Use this path when Talon is one service inside a larger typed system.
Option 2: CRUD with REST
The gateway exposes REST-transcoded endpoints through Envoy on http://localhost:18789.
Create a session:
curl -sS http://localhost:18789/v1/ns/client-demo/agents/docs-agent/sessions \
-X POST \
-H 'content-type: application/json' \
-d '{"ns":"client-demo","agent":"docs-agent"}'
Fetch the session later:
curl -sS http://localhost:18789/v1/ns/client-demo/agents/docs-agent/sessions/<session-id>
Use this path for scripts, ops tooling, and quick integration tests.
Option 3: browser chat with the UI session surface
For browser-native chat, create the session through CRUD first, then post messages to:
POST /v1/ui/ns/<namespace>/agents/<agent>/sessions/<session-id>
Example request:
curl -sS http://localhost:18789/v1/ui/ns/client-demo/agents/docs-agent/sessions/<session-id> \
-X POST \
-H 'content-type: application/json' \
-d '{"messages":[{"content":"Summarize the namespace model."}]}'
The body shape is the same one used by Sightline and the copilot package.
Fastest React path
If you want a working chat panel instead of building the stream parser yourself, use @impalasys/talon-chat.
import { TalonCopilot } from "@impalasys/talon-chat";
export function App() {
return (
<TalonCopilot
namespace="client-demo"
agent="docs-agent"
gatewayUrl="http://localhost:18789"
/>
);
}
That component handles:
- session creation
- the UI session POST
- transcript hydration from the canonical session state
- streamed tool and reasoning events
The minimal package usage is documented in packages/talon-chat/README.md.
What to avoid
- Do not invent a separate backend just to proxy browser chat unless you need app-specific auth or policy.
- Do not send browser chat traffic to the CRUD
messageroute if you want the same behavior Sightline uses. - Do not document schedule creation as a manifest-apply flow; Talon currently creates schedules through the gateway API.