Overview
Once your agent runs, whether locally or on Distri Cloud, it's reachable over a streaming API, and the SDK turns that into a chat UI your users can talk to. This page is the whole client surface in one place: set up the client, render a chat, wire your product's functions as tools, and point it at the right server.
Distri ships two first-party UI SDKs, both on the same client and streaming protocol. Pick your framework. Everything below has a tab for each.
- React:
@distri/react - Angular (17+):
@distri/angularNew
See Packages for install commands.
1. Set up the client
Register the client once, near the root of your app.
- React
- Angular
Wrap your tree in DistriProvider:
import { DistriProvider } from '@distri/react';
function App() {
return (
<DistriProvider config={{ baseUrl: 'http://localhost:7777' }}>
<YourComponents />
</DistriProvider>
);
}
Provide the client in bootstrapApplication:
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideDistri } from '@distri/angular';
export const appConfig: ApplicationConfig = {
providers: [
provideDistri({ baseUrl: 'http://localhost:7777/v1' }),
],
};
2. Render a chat
- React
- Angular
Load an agent with useAgent, then hand it to <Chat>:
import { Chat, useAgent } from '@distri/react';
function Assistant() {
const { agent } = useAgent({ agentIdOrDef: 'assistant' });
if (!agent) return <div>Loading…</div>;
return <Chat agent={agent} threadId="my-conversation" enableHistory />;
}
Drop in <distri-chat>. It picks the client up from DI:
import { Component } from '@angular/core';
import { DistriChatComponent } from '@distri/angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [DistriChatComponent],
template: `<distri-chat [agentIdOrDef]="agentId" [threadId]="threadId" />`,
})
export class AppComponent {
agentId = 'assistant';
threadId = crypto.randomUUID();
}
That's a working, streaming chat. Everything below is for when you want more.
3. Connect your product's functions
The reason to embed an agent instead of linking to a chatbot: it can call your functions, like filling in a form, selecting a row, or panning a map. You pass those as external tools.
- React
- Angular
import { Chat, useAgent } from '@distri/react';
import { createMapTools } from './tools';
function Maps() {
const { agent } = useAgent({ agentIdOrDef: 'maps_agent' });
const mapRef = useRef(null);
const tools = useMemo(() => createMapTools(mapRef), []);
if (!agent) return null;
return <Chat agent={agent} threadId="trip" externalTools={tools} />;
}
import { DistriBaseTool } from '@distri/core';
@Component({
/* … */
template: `<distri-chat [agentIdOrDef]="agentId" [threadId]="threadId"
[externalTools]="tools" />`,
})
export class MapsComponent {
readonly tools: DistriBaseTool[] = createMapTools(this.mapRef);
}
The full pattern, including tools that pause for user input (approvals, forms,
pickers), is in In-Product Tools.
@distri/react ships the ready-made UI for them.
4. Point at the right server
By default the client talks to whatever baseUrl you give it.
- Local server:
http://localhost:7777(React) /http://localhost:7777/v1(Angular). No auth. See Run a local server. - Distri Cloud:
https://api.distri.dev, with short-lived tokens your backend mints so an API key never reaches the browser.
- React
- Angular
<DistriProvider
config={{
baseUrl: 'https://api.distri.dev',
workspaceId: 'your-workspace-id',
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
onTokenRefresh: async () => {
const res = await fetch('/distri/token', { method: 'POST' });
return (await res.json()).access_token;
},
}}
>
<App />
</DistriProvider>
Point provideDistri at a token endpoint; the SDK fetches, attaches, and
re-mints the token for you:
provideDistri({ tokenEndpoint: '/api/distri/token' })
// endpoint returns { access_token, refresh_token, workspace_id, base_url? }
Your backend exchanges an API key for these short-lived tokens. See API Keys. The worked example below shows the full wiring against a local server.
The full hooks, props, services, and inputs are listed in the React & Angular API reference.
Worked example: a maps agent
This is a complete example: an agent that drives a Google Map through your own
tools, running against a local server. It ties together everything above: an
agent definition, client tools, and <Chat> beside your UI.
1. Define the agent (maps.md):
---
name = "maps_agent"
description = "Operate Google Maps tools to execute user instructions"
max_iterations = 3
[tools]
external = ["*"]
[model_settings]
model = "gpt-4.1-mini"
---
# ROLE
You are a decisive Google Maps agent. Follow user instructions directly and
execute with tools. Be brief and action-first.
# CAPABILITIES
- set_map_center: Center the map at latitude, longitude with optional zoom (1 to 20).
- add_marker: Place a titled marker at latitude, longitude.
- get_directions: Route summary between origin and destination.
- search_places: Find places near latitude, longitude within a radius.
- clear_map: Remove all markers and directions.
2. Define the client tools. Each one calls into your map component:
import type { DistriFnTool } from '@distri/core';
import type { GoogleMapsManagerRef } from './GoogleMapsManager';
export const getTools = (map: GoogleMapsManagerRef): DistriFnTool[] => [
{
name: 'set_map_center',
description: 'Center the map',
type: 'function',
parameters: {
type: 'object',
properties: {
latitude: { type: 'number' },
longitude: { type: 'number' },
zoom: { type: 'number', minimum: 1, maximum: 20, default: 13 },
},
required: ['latitude', 'longitude'],
},
handler: async ({ latitude, longitude, zoom }) => {
await map.setMapCenter({ latitude, longitude, zoom });
return `Map centered at ${latitude}, ${longitude}`;
},
},
// add_marker, get_directions, search_places, clear_map …
];
See In-Product Tools for the full tool API.
3. Render the chat beside the map:
import { useRef, useState, useCallback } from 'react';
import { DistriProvider, Chat, useAgent, DistriAnyTool } from '@distri/react';
import GoogleMapsManager, { GoogleMapsManagerRef } from './GoogleMapsManager';
import { getTools } from './Tools';
export function App() {
return (
<DistriProvider config={{ baseUrl: 'http://localhost:7777' }}>
<MapsContent />
</DistriProvider>
);
}
function MapsContent() {
const { agent } = useAgent({ agentIdOrDef: 'maps_agent' });
const [threadId] = useState(() => crypto.randomUUID());
const mapRef = useRef<GoogleMapsManagerRef>(null);
const [tools, setTools] = useState<DistriAnyTool[]>([]);
const handleReady = useCallback((instance: GoogleMapsManagerRef) => {
setTools(getTools(instance));
}, []);
if (!agent) return null;
return (
<div className="maps-layout">
<GoogleMapsManager ref={mapRef} onReady={handleReady} />
<Chat agent={agent} threadId={threadId} externalTools={tools} />
</div>
);
}