Skip to main content

Overview

The @standardagents/client package provides the core client library for Standard Agents. It’s a framework-agnostic foundation that @standardagents/react and @standardagents/vue build upon.

Key Features

  • HTTP client for all API operations
  • WebSocket connection management with auto-reconnection
  • File upload handling with thumbnail generation
  • Utility functions for workblocks and attachments
  • Zero framework dependencies

Installation

npm
npm install @standardagents/client
pnpm
pnpm add @standardagents/client
yarn
yarn add @standardagents/client
Most users should use @standardagents/react or @standardagents/vue instead, which re-export everything from this package with additional framework-specific features.

AgentBuilderClient

HTTP client for all Standard Agents API operations.
import { AgentBuilderClient } from '@standardagents/client'

const client = new AgentBuilderClient({
  endpoint: 'https://your-api.com',
  token: 'your-auth-token',
})

// Create a thread
const thread = await client.createThread({
  agentId: 'support-agent',
})

// Send a message
const message = await client.sendMessage(thread.id, {
  role: 'user',
  content: 'Hello!',
})

// Get message history
const messages = await client.getMessages(thread.id, { limit: 50 })

Methods

MethodDescription
createThread(payload)Create a new thread
getThread(threadId)Fetch thread metadata
getMessages(threadId, options?)Fetch message history
sendMessage(threadId, payload)Send a user message
stopExecution(threadId)Cancel in-flight execution
uploadFile(threadId, file, path?)Upload a file to thread filesystem
listFiles(threadId, path?)List files in thread filesystem
getFile(threadId, path)Download a file
deleteFile(threadId, path)Delete a file

Configuration

interface AgentBuilderConfig {
  endpoint: string    // API endpoint URL
  token?: string      // Optional auth token
}

ThreadConnectionManager

Manages WebSocket connections with automatic reconnection and heartbeat.
import { ThreadConnectionManager } from '@standardagents/client'

const manager = new ThreadConnectionManager({
  endpoint: 'https://your-api.com',
  threadId: 'thread-123',
  token: 'your-auth-token',
  onMessage: (message) => console.log('Message:', message),
  onChunk: (chunk) => console.log('Chunk:', chunk),
  onStatusChange: (status) => console.log('Status:', status),
  onError: (error) => console.error('Error:', error),
})

// Connect to both message and log WebSockets
manager.connect()

// Disconnect when done
manager.disconnect()

Connection Features

  • Auto-reconnection: Exponential backoff (1s → 2s → 4s → … → 30s max)
  • Heartbeat: Ping every 30 seconds to keep connection alive
  • Status tracking: connecting, connected, reconnecting, disconnected

Options

interface ThreadConnectionOptions {
  endpoint: string
  threadId: string
  token?: string
  onMessage?: (message: Message) => void
  onChunk?: (chunk: MessageChunkEvent) => void
  onLog?: (log: LogDataEvent) => void
  onCustomEvent?: (event: CustomEvent) => void
  onStatusChange?: (status: ConnectionStatus) => void
  onError?: (error: Error) => void
}

FileUploadManager

Handles file uploads with thumbnail generation and progress tracking.
import { FileUploadManager } from '@standardagents/client'

const uploader = new FileUploadManager({
  endpoint: 'https://your-api.com',
  threadId: 'thread-123',
  token: 'your-auth-token',
})

// Upload with progress callback
const result = await uploader.upload(file, {
  path: '/uploads/image.png',
  onProgress: (progress) => console.log(`${progress}%`),
})

Features

  • Thumbnail generation: Automatic for image files
  • Progress tracking: Callbacks for upload progress
  • Deferred uploads: Returns pending refs before upload completes

Utility Functions

transformToWorkblocks

Groups tool calls with their results for UI rendering.
import { transformToWorkblocks } from '@standardagents/client'

const messages = await client.getMessages(threadId)
const workblocks = transformToWorkblocks(messages)

// Workblocks group consecutive tool calls:
// [assistant with tool_calls, tool result, tool result, assistant]
// becomes:
// [workblock { workItems: [...] }, assistant]

parseAttachments

Extract attachment references from message content.
import { parseAttachments } from '@standardagents/client'

const attachments = parseAttachments(message.attachments)
// Returns: AttachmentRef[]

Image Processing

import {
  generateImageThumbnail,
  canGenerateThumbnails,
} from '@standardagents/client'

// Check if thumbnails are supported (requires Canvas API)
if (canGenerateThumbnails()) {
  const thumbnail = await generateImageThumbnail(file, {
    maxWidth: 200,
    maxHeight: 200,
  })
}

File Helpers

import {
  generatePendingFileId,
  readFileAsDataUrl,
  isImageMimeType,
  messagesToFiles,
} from '@standardagents/client'

// Generate unique ID for pending uploads
const id = generatePendingFileId()

// Read file as data URL
const dataUrl = await readFileAsDataUrl(file)

// Check if MIME type is an image
isImageMimeType('image/png') // true

// Extract files from messages
const files = messagesToFiles(messages)

Type Exports

The package exports all types needed for building clients:
import type {
  // Core message types
  Message,
  WorkMessage,
  WorkItem,
  ThreadMessage,
  Thread,

  // Attachment types
  AttachmentRef,
  ThreadFile,
  PendingAttachment,
  AttachmentPayload,

  // Configuration
  AgentBuilderConfig,

  // Request/Response types
  GetMessagesOptions,
  SendMessagePayload,
  CreateThreadPayload,

  // WebSocket event types
  MessageDataEvent,
  MessageChunkEvent,
  ErrorEvent,
  ThreadEvent,
  MessageStreamEvent,
  LogDataEvent,
  CustomEvent,
  StoppedByUserEvent,
  LogStreamEvent,

  // Callback types
  MessageWebSocketCallbacks,
  LogWebSocketCallbacks,
  ThreadConnectionCallbacks,

  // Connection status
  ConnectionStatus,
} from '@standardagents/client'

Key Types

Message:
interface Message {
  id: string
  role: 'system' | 'user' | 'assistant' | 'tool'
  content: string | null
  name?: string | null
  tool_calls?: string | null
  tool_call_id?: string | null
  created_at: number
  status?: 'pending' | 'completed' | 'failed'
  attachments?: string | null
}
PendingAttachment:
interface PendingAttachment {
  id: string
  file: File
  name: string
  mimeType: string
  size: number
  isImage: boolean
  previewUrl: string | null
  width?: number
  height?: number
}
AttachmentRef:
interface AttachmentRef {
  id: string
  type: 'file'
  path: string
  name: string
  mimeType: string
  size: number
  width?: number
  height?: number
  description?: string
}
ConnectionStatus:
type ConnectionStatus = 'connecting' | 'connected' | 'reconnecting' | 'disconnected'

Authentication

The client reads auth tokens from localStorage:
// Token is read from this key
const token = localStorage.getItem('agentbuilder_auth_token')

// Included in requests as:
// Authorization: Bearer {token}
You can also pass the token directly to the client:
const client = new AgentBuilderClient({
  endpoint: 'https://your-api.com',
  token: 'your-auth-token',
})

Building Custom Integrations

Use @standardagents/client directly when:
  • Building for a framework without an official SDK
  • Creating custom tooling or CLI applications
  • Building server-side integrations
  • Needing fine-grained control over connections
import {
  AgentBuilderClient,
  ThreadConnectionManager,
  transformToWorkblocks,
} from '@standardagents/client'

class CustomChatClient {
  private client: AgentBuilderClient
  private connection: ThreadConnectionManager | null = null
  private messages: Message[] = []

  constructor(endpoint: string, token: string) {
    this.client = new AgentBuilderClient({ endpoint, token })
  }

  async connect(threadId: string) {
    // Load existing messages
    this.messages = await this.client.getMessages(threadId)

    // Set up live connection
    this.connection = new ThreadConnectionManager({
      endpoint: this.client.endpoint,
      threadId,
      token: this.client.token,
      onMessage: (msg) => {
        this.messages.push(msg)
        this.onUpdate?.(transformToWorkblocks(this.messages))
      },
    })

    this.connection.connect()
  }

  async send(content: string) {
    await this.client.sendMessage(this.threadId, {
      role: 'user',
      content,
    })
  }

  onUpdate?: (workblocks: ThreadMessage[]) => void
}

Next Steps