Skip to main content

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.

See Packages for install commands.

1. Set up the client

Register the client once, near the root of your app.

Wrap your tree in DistriProvider:

import { DistriProvider } from '@distri/react';

function App() {
return (
<DistriProvider config={{ baseUrl: 'http://localhost:7777' }}>
<YourComponents />
</DistriProvider>
);
}

2. Render a chat

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 />;
}

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.

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} />;
}

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.
<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>

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>
);
}

Next