@standardagents/client
v0.41.12
Published
Framework-agnostic client for Standard Agents
Readme
@standardagents/client
Framework-agnostic client library for Standard Agents - provides HTTP/WebSocket communication, connection management, and shared utilities used by @standardagents/react and @standardagents/vue.
Installation
npm install @standardagents/client
# or
pnpm add @standardagents/client
# or
yarn add @standardagents/clientNote: Most users should use
@standardagents/reactor@standardagents/vueinstead. This package is for advanced use cases or building custom framework integrations.
Quick Start
import { AgentBuilderClient, ThreadConnectionManager } from '@standardagents/client'
// Create a client. The endpoint may be absolute or same-origin relative.
const client = new AgentBuilderClient('https://api.example.com')
// const client = new AgentBuilderClient('/api')
// Fetch messages from a thread
const messages = await client.getMessages('thread-123')
// Send a message
await client.sendMessage('thread-123', {
role: 'user',
content: 'Hello!',
})
// Connect to live updates with automatic reconnection
const connection = new ThreadConnectionManager(client, 'thread-123', {
onStatusChange: (status) => console.log('Status:', status),
onMessage: (event) => console.log('New message:', event.data),
onChunk: (event) => console.log('Streaming chunk:', event.chunk),
onEvent: (event) => console.log('Custom event:', event.eventType, event.data),
})
connection.connect()Authentication
The client reads the authentication token from localStorage using the key agentbuilder_auth_token when making API requests or opening WebSocket connections:
// Set or replace the token before making requests or opening live connections.
localStorage.setItem('agentbuilder_auth_token', 'your-token-here')All API requests and WebSocket connections will automatically include this token.
API Reference
AgentBuilderClient
HTTP client for the Standard Agents API.
Constructor
const client = new AgentBuilderClient(endpoint: string)Methods
getEndpoint(): string
Returns the configured endpoint URL.
createThread(payload): Promise<Thread>
Create a new thread.
const thread = await client.createThread({
agent_id: 'my-agent',
user_id: 'user-123', // optional
})getThread(threadId): Promise<Thread>
Get thread metadata.
const thread = await client.getThread('thread-123')getMessages(threadId, options?): Promise<Message[]>
Fetch messages from a thread.
const messages = await client.getMessages('thread-123', {
limit: 50,
offset: 0,
depth: 0,
includeSilent: false,
})Use getMessagesPage() when you need pagination metadata, or pass ids to
hydrate specific messages. includeWorkblocks expands requested tool-call
messages to the complete workblock they belong to.
sendMessage(threadId, payload): Promise<Message>
Send a message to a thread.
const message = await client.sendMessage('thread-123', {
role: 'user',
content: 'Hello!',
silent: false, // optional
})stopExecution(threadId): Promise<void>
Cancel an in-flight execution.
await client.stopExecution('thread-123')connectMessageWebSocket(threadId, callbacks?, options?): Promise<WebSocket>
Create a WebSocket connection for streaming messages. When a stored bearer is present, the client first mints a 30-second path-bound ticket so the long-lived credential never appears in the socket URL.
const ws = await client.connectMessageWebSocket('thread-123', {
onOpen: () => console.log('Connected'),
onMessage: (event) => console.log('Message:', event),
onChunk: (event) => console.log('Chunk:', event),
onError: (event) => console.error('Error:', event),
onClose: (event) => console.log('Closed:', event),
}, {
includeSilent: false,
depth: 0,
})connectLogWebSocket(threadId, callbacks?): Promise<WebSocket>
Create a WebSocket connection for log events and custom events.
const ws = await client.connectLogWebSocket('thread-123', {
onOpen: () => console.log('Connected'),
onLog: (event) => console.log('Log:', event),
onCustom: (event) => console.log('Custom:', event),
onStopped: (event) => console.log('Stopped:', event),
onClose: (event) => console.log('Closed:', event),
})ThreadConnectionManager
Manages WebSocket connections with automatic reconnection and heartbeat.
Constructor
const manager = new ThreadConnectionManager(
client: AgentBuilderClient,
threadId: string,
callbacks?: ThreadConnectionCallbacks,
options?: ThreadConnectionOptions
)Callbacks:
onStatusChange?: (status: ConnectionStatus) => void- Called when connection status changesonMessage?: (event: MessageDataEvent) => void- Called when a complete message is receivedonChunk?: (event: MessageChunkEvent) => void- Called when a streaming chunk is receivedonEvent?: (event: ThreadEvent) => void- Called when a custom event is receivedonError?: (error: Error | Event) => void- Called on connection errors
Options:
depth?: number- Message depth level (default:0)includeSilent?: boolean- Include silent messages (default:false). Framework grouping keeps explicitly included silent messages in chronological output.maxReconnectDelay?: number- Max reconnection delay in ms (default:30000)heartbeatInterval?: number- Heartbeat interval in ms (default:30000)
Methods
connect(): void
Establish the WebSocket connection.
disconnect(): void
Close the connection and stop reconnection attempts.
getStatus(): ConnectionStatus
Returns the current connection status: 'connecting' | 'connected' | 'reconnecting' | 'disconnected'
getThreadId(): string
Returns the thread ID.
updateCallbacks(callbacks): void
Update callbacks after construction.
updateOptions(options): void
Update options after construction.
Reconnection Behavior
The connection manager automatically reconnects on unexpected disconnections using exponential backoff:
- Initial delay: 1 second
- Doubles each attempt: 1s, 2s, 4s, 8s, 16s
- Maximum delay: 30 seconds (configurable)
- Resets to 1s after successful connection
transformToWorkblocks(messages): ThreadMessage[]
Groups tool calls with their results into workblock structures for easier UI rendering.
import { transformToWorkblocks } from '@standardagents/client'
const messages = await client.getMessages('thread-123')
const workblocks = transformToWorkblocks(messages)
// Each workblock contains:
// - type: 'workblock'
// - workItems: array of tool calls and results
// - log_ids: log IDs for LLM requests represented by the block
// - status: 'pending' | 'completed'transformToSubagentBlocks(messages, options): SubagentThreadMessage[]
Groups referenced child traffic into timeline-aware subagent blocks. Pending
agent-as-tool launches may appear immediately, but runtime lifecycle calls such
as subagent_create, subagent_message, and subagents remain ordinary tool
work until an actual child reference exists. Use currentThreadId to exclude
the viewed thread from child cards and preserveSilentMessages for an operator
transcript that explicitly includes silent messages.
Types
import type {
Message,
WorkMessage,
WorkItem,
ThreadMessage,
Thread,
SendMessagePayload,
GetMessagesOptions,
CreateThreadPayload,
ConnectionStatus,
ThreadConnectionCallbacks,
ThreadConnectionOptions,
} from '@standardagents/client'Message Types
interface Message {
id: string
role: 'user' | 'assistant' | 'system' | 'tool'
content: string | null
created_at: number // microseconds
reasoning_content?: string | null
silent?: boolean
depth?: number
tool_calls?: string // JSON string
tool_call_id?: string
}
interface WorkMessage {
type: 'workblock'
id: string
content: string | null
reasoning_content?: string | null
status: 'pending' | 'completed'
workItems: WorkItem[]
log_ids?: string[]
created_at: number
depth?: number
}
interface WorkItem {
id: string
type: 'tool_call' | 'tool_result'
name: string
input?: string
content?: string
status: 'success' | 'error' | null
tool_call_id?: string
log_id?: string | null
}
type ThreadMessage = Message | WorkMessageLocal Development
# Install dependencies
pnpm install
# Build package
pnpm build
# Watch mode
pnpm dev
# Type check
pnpm typecheck
# Run tests
pnpm test