octoflow-react
v1.0.1
Published
Headless React bindings for OctoFlow: provider, chat/session/approval/provider hooks, and AI SDK UI / AG-UI adapters.
Downloads
273
Readme
@octoflow/react
Status: Preview. Transport compatibility tests are in progress. Pin versions before depending on it in production.
Headless React bindings for OctoFlow — browser-safe provider, hooks, and adapters. Not a UI component library.
Installation
npm install @octoflow/react react
# Optional adapters depending on your UI layer:
npm install @ag-ui/client
npm install @copilotkit/react-core @copilotkit/react-ui
npm install ai @ai-sdk/reactQuick Start
import {
OctoFlowProvider,
useOctoFlowChat,
useOctoFlowApprovals,
useOctoFlowProviders,
} from '@octoflow/react';
export function App() {
return (
<OctoFlowProvider baseUrl="/api/octoflow">
<Chat />
</OctoFlowProvider>
);
}
function Chat() {
const chat = useOctoFlowChat({ sessionId: 'support-thread-123' });
const approvals = useOctoFlowApprovals({ sessionId: chat.sessionId });
const providers = useOctoFlowProviders();
// Render with your own components, assistant-ui, CopilotKit, or AI SDK UI.
}Choose an Integration Path
| Path | Best for | Start with |
| --- | --- | --- |
| OctoFlowProvider + hooks | Custom product UI, custom approval surfaces, model/settings panels. | app-simple-chatbot |
| @octoflow/react/ag-ui + @ag-ui/client | Protocol-first AG-UI testing or a custom AG-UI renderer. | react-ag-ui-chatbot |
| CopilotKit + HttpAgent | Stock CopilotKit chat UI backed by OctoFlow. | react-copilotkit-ag-ui-chatbot |
| AI SDK UI | Existing @ai-sdk/react useChat apps. | react-ai-sdk-ui-chatbot |
Security: Keep Secrets Server-Side
OctoFlowProvider accepts only display-safe headers (CSRF tokens, short-lived
session tokens, tenant IDs). Provider API keys, filesystem grants, and backend
secrets must live in server route handlers, never in client components.
// app/api/octoflow/agui/run/route.ts (Next.js App Router)
import { createOctoFlowRouteHandler } from '@octoflow/react/server';
export const POST = createOctoFlowRouteHandler({
async authenticate(req) {
// Validate session cookie, JWT, etc.
return { userId: 'user-123' };
},
async runAgent(input, context) {
// Use octoflow-core here — API keys stay on the server.
},
});Hooks
useOctoFlowChat(options?)
OctoFlow-backed streaming chat over the AG-UI gateway.
const {
sessionId,
messages, // OctoFlowUIMessage[]
status, // 'ready' | 'submitted' | 'streaming' | 'error'
error,
sendMessage, // (input: { content, metadata? }) => Promise<void>
stop, // () => void — abort the current stream
regenerate, // (messageId?) => Promise<void>
resumeStream, // () => Promise<void> — no-op on basic transport
setMessages,
} = useOctoFlowChat({ sessionId?, initialMessages?, metadata?, resume? });useOctoFlowApprovals(options)
Pending approvals for a session with approve/deny actions.
const { pending, isLoading, error, approve, deny } =
useOctoFlowApprovals({ sessionId, pollIntervalMs?: 3000 });useOctoFlowProviders()
Backend/provider readiness catalog for settings UIs and model pickers.
const { providers, isLoading, error, refresh } = useOctoFlowProviders();useOctoFlowSessions()
Session list with delete support.
const { sessions, isLoading, error, refresh, deleteSession } =
useOctoFlowSessions();useOctoFlowClient()
Low-level access to the client context (baseUrl, resolveHeaders, fetchFn).
Subpath Exports
@octoflow/react/ai-sdk
AI SDK UI v4 helpers for @ai-sdk/react useChat and the ai package data stream protocol. Optional peer: ai.
import { createOctoFlowAiSdkUseChatOptions } from '@octoflow/react/ai-sdk';
import { useChat } from '@ai-sdk/react';
const chat = useChat(
createOctoFlowAiSdkUseChatOptions({
api: '/api/chat',
sessionId,
})
);Server routes can use writeOctoFlowAiSdkText, writeOctoFlowAiSdkData, and writeOctoFlowAiSdkFinish to bridge OctoFlow session streams into AI SDK UI data streams.
@octoflow/react/ag-ui
AG-UI helpers for CopilotKit, assistant-ui, and direct @ag-ui/client usage.
Optional peer: @ag-ui/client.
import { HttpAgent } from '@ag-ui/client';
import { createOctoFlowAguiConfig } from '@octoflow/react/ag-ui';
const { url, headers } = createOctoFlowAguiConfig({ baseUrl: '/api/octoflow' });
const agent = new HttpAgent({ url, headers });For CopilotKit, pass that HttpAgent as the local agent behind <CopilotKit> and render <CopilotChat> from @copilotkit/react-ui. The full example is react-copilotkit-ag-ui-chatbot.
@octoflow/react/server
Server-only route handler factory. Node.js / Next.js / edge runtime safe.
import { createOctoFlowRouteHandler } from '@octoflow/react/server';Building a Full UI
@octoflow/react is headless — it gives you the data, you supply the components. Here is the recommended component architecture:
<OctoFlowProvider> ← one per app/layout; holds HTTP config
<ChatPanel /> ← useOctoFlowChat (streaming, send, stop, regenerate)
<ApprovalQueue /> ← useOctoFlowApprovals (poll + approve/deny)
<BackendStatus /> ← useOctoFlowProviders (readiness badge)
<SessionHistory /> ← useOctoFlowSessions (list + delete)
</OctoFlowProvider>Performance pattern — useDeferredValue for the message list
Every streaming token triggers setMessages. Wrapping the message list in useDeferredValue lets React defer expensive re-renders while keeping the input and status badge responsive:
import { useDeferredValue } from 'react';
function ChatPanel() {
const chat = useOctoFlowChat();
// Defer the expensive message list — stays stale during fast streaming
// but the textarea and status badge (chat.status) update immediately.
const deferredMessages = useDeferredValue(chat.messages);
const isUpdating = deferredMessages !== chat.messages;
return (
<>
<StatusBadge status={chat.status} /> {/* always current */}
<ul style={{ opacity: isUpdating ? 0.8 : 1 }}>
{deferredMessages.map((m) => (
<MessageRow key={m.id} message={m} />
))}
</ul>
<textarea onKeyDown={...} /> {/* always responsive */}
</>
);
}useOctoFlowChat already wraps every streaming token update in startTransition, so message list re-renders are non-urgent by default. Pair with useDeferredValue for extra smoothness on long conversations.
Memo individual message rows
Because setMessages returns a new array on every token, wrap individual message components with React.memo to prevent full-list re-renders:
const MessageRow = React.memo(function MessageRow({ message }: { message: OctoFlowUIMessage }) {
return <li className={`msg msg-${message.role}`}>{message.content}</li>;
});Plugging in an existing UI library
| UI library | Integration path |
| --- | --- |
| assistant-ui | Use @octoflow/react/ag-ui to get the AG-UI config → pass to @assistant-ui/react-ag-ui |
| CopilotKit | Use @octoflow/react/ag-ui → HttpAgent → <CopilotKit localRuntimeUrl={...}> |
| AI SDK UI useChat | Use @octoflow/react/ai-sdk → createOctoFlowAiSdkUseChatOptions |
| Custom shadcn/ui | Use useOctoFlowChat directly — messages, status, and sendMessage map 1:1 |
Stream Transport Pluggability
@octoflow/react uses a fixed SSE transport (POST to /agui/run, read AG-UI events). To swap the transport or integrate with a different backend shape:
Option A — Custom fetch (same protocol, different auth/proxy):
<OctoFlowProvider
baseUrl="/api/octoflow"
customFetch={async (input, init) => {
// Add auth headers, inject tenant id, route to a different host, etc.
return fetch(input, { ...init, headers: { ...init?.headers, 'X-Tenant': 'acme' } });
}}
>Option B — Custom route handler (server-side: different agent, model, or tool set per tenant):
// app/api/octoflow/agui/run/route.ts
import { createOctoFlowRouteHandler } from '@octoflow/react/server';
export const POST = createOctoFlowRouteHandler({
authenticate: (req) => verifyJwt(req),
runAgent: async (input, ctx) => {
// Swap agent, model, tool set, or execution environment per request.
const agent = await pickAgent(ctx.auth);
return agent.run(input); // returns ReadableStream or AsyncIterable<string>
},
});Option C — AG-UI protocol adapter (different frontend UI library):
import { createOctoFlowAguiConfig } from '@octoflow/react/ag-ui';
import { HttpAgent } from '@ag-ui/client';
// Same server, different client library:
const config = createOctoFlowAguiConfig({ baseUrl: '/api/octoflow' });
const agent = new HttpAgent(config); // works with any AG-UI-compatible UIAG-UI and hooks — unified contract: Every integration path (hooks, AG-UI, AI SDK UI, CopilotKit) connects to the same OctoFlow server endpoint (/agui/run). The endpoint speaks the AG-UI SSE protocol — useOctoFlowChat parses it natively, while the @octoflow/react/ag-ui subpath exposes the raw config for third-party AG-UI clients. Choose the integration path based on your UI layer, not your backend.
Integration Examples
| Framework | Path |
| --- | --- |
| Headless React hooks (canonical) | packages/octoflow-examples/src/apps/app-react-hooks-chatbot/ |
| Raw AG-UI client | packages/octoflow-examples/src/apps/app-react-ag-ui-chatbot/ |
| CopilotKit / AG-UI | packages/octoflow-examples/src/apps/app-react-copilotkit-ag-ui-chatbot/ |
| AI SDK UI | packages/octoflow-examples/src/apps/app-react-ai-sdk-ui-chatbot/ |
| assistant-ui | Use @octoflow/react/ag-ui config → @assistant-ui/react-ag-ui |
Transport Capabilities
Current default capabilities (OCTOFLOW_REACT_DEFAULT_CAPABILITIES):
| Capability | Supported |
| --- | --- |
| Streaming text | ✅ |
| Tool calls | ✅ |
| Tool results | ✅ |
| Approvals | ✅ |
| Provider catalog | ✅ |
| State sync (STATE_SNAPSHOT/DELTA) | ❌ (post-MVP) |
| Interrupt/resume | ❌ (post-MVP) |
| Reconnect/resume stream | ❌ (post-MVP) |
Validation
npm run -w octoflow-react lint
npm run -w octoflow-react typecheck
npm run -w octoflow-react testPackage Boundaries
@octoflow/react(root) — browser-safe; nooctoflow-coreimport; React peer only.@octoflow/react/ag-ui— browser-safe; optional@ag-ui/clientpeer.@octoflow/react/server— server/node; may depend onoctoflow-corevia therunAgentcallback.
Status
Marked Preview until:
- Transport compatibility tests pass.
- AI SDK UI / AG-UI examples are runnable.
- Approval and session semantics are documented per transport.
- Gateway beta/preview caveats are explicit in each hook's docs.
See docs/ag-ui.md and the package tests for the supported transport behavior.
