@fellow.work/client
v0.1.7
Published
Fellow SDK — headless Gateway client, AG-UI streaming, and optional React embed UI
Readme
@fellow.work/client
Fellow SDK — headless Gateway client (Thread/Run + AG-UI streaming) and optional React embed UI.
Install
npm install @fellow.work/client
# React widget (optional):
npm install react react-domRequires Node 22+ or a modern browser with fetch and ReadableStream.
Quick start (server)
Create an Integration App in Fellow Console and copy the API key (fkey_…).
import { createClient, EventType } from '@fellow.work/client';
const client = createClient({
baseUrl: 'https://your-fellow-host/api',
apiKey: process.env.FELLOW_APP_API_KEY!,
});
const { id: threadId } = await client.createThread();
const { events } = await client.run(threadId, { content: 'Hello' }, { reconnect: true });
for await (const event of events) {
if (event.type === EventType.TEXT_MESSAGE_CONTENT) {
process.stdout.write(event.delta);
}
}See examples/app-key.mjs.
Browser (access token)
Never ship fkey_ to the browser. Your backend exchanges it for a short-lived OAuth-style token:
// Backend
const { access_token } = await serverClient.createAccessToken({
origin: 'https://your-app.com',
external_user_id: userId,
});
// Frontend — headless
const client = createClient({
baseUrl: 'https://your-fellow-host/api',
accessToken: access_token,
});See examples/access-token.mjs.
React UI (same package)
Full UI (FellowChat)
Embedded in a host app (first-party web/desktop): styles load automatically — wrap chat UI in .fellow-web-chat (done inside FellowChat / ChatInputPanel usage).
import { FellowChat } from '@fellow.work/client/react';
<FellowChat baseUrl="https://your-fellow-host/api" accessToken={token} host />Import styles once (Full UI + Widget + site preset):
import '@fellow.work/client/ui.css';
import { FellowChat } from '@fellow.work/client/react';
<FellowChat baseUrl="https://your-fellow-host/api" accessToken={token} host />Lite widget (FellowChatWidget)
import '@fellow.work/client/ui.css';
import { FellowChatWidget } from '@fellow.work/client/react';
<FellowChatWidget
baseUrl="https://your-fellow-host/api"
accessToken={token}
externalUserId={userId}
labels={{
title: 'Support',
launcher: 'Help',
placeholder: 'How can we help?',
empty: 'Start a conversation.',
send: 'Send',
stop: 'Stop',
close: 'Close chat',
}}
theme={{
accent: '#0f172a',
userMessageBg: '#0f172a',
launcherBg: '#0f172a',
}}
classNames={{ sendButton: 'my-send-btn' }}
components={{
Launcher: ({ label, onClick, className }) => (
<button type="button" className={className} onClick={onClick}>{label}</button>
),
}}
/>Also available: FellowChatLite (inline lite panel), useFellowChat (headless hook).
Customization props: labels (i18n copy), theme (CSS variables), classNames, components (launcher / send / stop / close).
Script embed (no React required)
For plain HTML, WordPress, PHP, or any site without a React build step, load the self-contained IIFE bundle. React is bundled inside embed.js.
<link rel="stylesheet" href="https://your-cdn/fellow-widget.css" />
<script src="https://your-cdn/fellow-embed.js"></script>
<script>
Fellow.init({
mode: 'widget', // default — floating launcher + popup panel
baseUrl: 'https://your-fellow-host/api',
accessToken: tokenFromYourBackend,
locale: 'zh',
});
</script>Inline mode mounts into a container:
<div id="support-chat" style="height:520px"></div>
<script>
Fellow.init({
mode: 'inline',
container: '#support-chat',
baseUrl: 'https://your-fellow-host/api',
accessToken: tokenFromYourBackend,
});
</script>Declarative auto-mount:
<div
data-fellow-widget
data-fellow-base-url="https://your-fellow-host/api"
data-fellow-access-token="..."
style="height:520px"
></div>
<script src="https://your-cdn/fellow-embed.js"></script>Build artifacts: dist/embed.js (~400KB minified, ~125KB gzip), dist/widget.css.
Local demo (same dev server as the playground):
cp packages/client/.env.example packages/client/.env
# set FELLOW_APP_API_KEY=fkey_… (allowedOrigins must include http://localhost:5180)
pnpm dev:client
# → http://localhost:5180Print an access token from the CLI (server-side):
pnpm --filter @fellow.work/client fetch-tokenQueue calls before the script loads:
<script>
window.Fellow = { q: [] };
window.Fellow.init = (cfg) => window.Fellow.q.push(cfg);
</script>
<script src="https://your-cdn/fellow-embed.js"></script>hostContext, tools, and onToolCall are supported via Fellow.init({ ... }) for page-context integrations.
Local dev playground
Debug React UI inside the package with Vite (hot-reloads src/, no dist/ build):
cp packages/client/.env.example packages/client/.env.local
# set FELLOW_APP_API_KEY + Gateway running
pnpm dev:client
# → http://localhost:5180The playground exercises FellowChat (full chat) and FellowChatWidget (lite floating embed). Toggle previewMode, features, labels, and theme live.
Uses a dev-only /dev/access-token route (reads FELLOW_APP_API_KEY server-side). Integration App allowed_origins must include http://localhost:5180.
Monorepo consumers in development can also resolve development export conditions to src/ (Next.js transpilePackages).
Publish to npm
pnpm publish:clientBuild only (no upload): pnpm dist:client
Published dist/*.js is obfuscated. Type declarations and CSS stay readable.
License
See LICENSE in the repository root.
