### Setup Development Environment for Helix AI Source: https://agents.open-source.onhelix.ai/examples/resumable-streams-nextjs This snippet outlines the necessary steps to set up a local development environment for Helix AI, including starting Redis, installing dependencies, configuring environment variables, and running the development server. ```bash # Start Redis docker-compose up -d # Install dependencies npm install # Configure environment cp .env.example .env # Edit .env and add your OpenAI API key # Run the development server npm run dev # Open http://localhost:3000 ``` -------------------------------- ### Integration Tests Setup - Bash Source: https://agents.open-source.onhelix.ai/internals/contributing Instructions for running integration tests, which require external services. This involves starting the services using Docker Compose and then executing the integration tests via npm. ```bash # Start services docker-compose up -d # Run integration tests npm run test:integration ``` -------------------------------- ### Complete Research Agent Example (TypeScript) Source: https://agents.open-source.onhelix.ai/guide/getting-started This comprehensive example defines a research agent, including its tools, system prompt, output schema, and LLM configuration. It then sets up an executor and runs the agent to research a given topic, streaming the output and displaying the final structured result. This code is intended to be run as a single file. ```typescript // research-agent.ts import { defineAgent, defineTool } from '@helix-agents/sdk'; import { JSAgentExecutor, InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/sdk'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; // Output schema const ResearchOutputSchema = z.object({ topic: z.string(), summary: z.string(), keyPoints: z.array(z.string()), sources: z.array(z.string()), }); // Search tool const searchTool = defineTool({ name: 'search', description: 'Search the web for information', inputSchema: z.object({ query: z.string() }), outputSchema: z.object({ results: z.array( z.object({ title: z.string(), url: z.string(), snippet: z.string(), }) ), }), execute: async ({ query }) => ({ results: [ { title: `${query} - Wikipedia`, url: `https://wikipedia.org`, snippet: `Info about ${query}`, }, ], }), }); // Agent definition const ResearchAgent = defineAgent({ name: 'research-assistant', systemPrompt: 'You are a research assistant. Search for info and provide summaries.', tools: [searchTool], outputSchema: ResearchOutputSchema, llmConfig: { model: openai('gpt-4o-mini') }, maxSteps: 10, }); // Execute async function main() { const executor = new JSAgentExecutor( new InMemoryStateStore(), new InMemoryStreamManager(), new VercelAIAdapter() ); const handle = await executor.execute(ResearchAgent, 'Benefits of TypeScript', { sessionId: 'my-session-1', }); for await (const chunk of (await handle.stream()) ?? []) { if (chunk.type === 'text_delta') process.stdout.write(chunk.delta); } const result = await handle.result(); console.log('\n\nOutput:', JSON.stringify(result.output, null, 2)); } main(); ``` -------------------------------- ### Run Research Agent Example (Bash) Source: https://agents.open-source.onhelix.ai/guide/getting-started This command shows how to execute the complete research agent example using tsx. It requires the OPENAI_API_KEY environment variable to be set with your OpenAI API key. ```bash OPENAI_API_KEY=sk-your-key npx tsx research-agent.ts ``` -------------------------------- ### Install Helix Agents SDK and LLM Adapter Source: https://agents.open-source.onhelix.ai/guide/getting-started Installs the necessary packages for Helix Agents, including the core SDK, a Vercel LLM adapter, the OpenAI SDK, and Zod for schema definition. Ensure Node.js 22+ and npm 11+ are installed. ```bash npm install @helix-agents/sdk @helix-agents/llm-vercel @ai-sdk/openai zod ``` -------------------------------- ### Quick Start with FrontendHandler for AI SDK Source: https://agents.open-source.onhelix.ai/guide/resumable-streams Shows a quick start example for the Helix Agents AI SDK using `createFrontendHandler`. This handler simplifies frontend integration by automatically managing resumability and providing a snapshot of the current state, including messages, agent state, and stream sequence. ```typescript import { createFrontendHandler } from '@helix-agents/ai-sdk'; const handler = createFrontendHandler({ streamManager, executor, agent: MyAgent, stateStore, // Content replay is enabled by default }); // Get snapshot for initializing UI const snapshot = await handler.getSnapshot(sessionId); // snapshot contains: // - messages: UIMessage[] (for initialMessages) // - state: AgentState (custom state) // - streamSequence: number (resume position) // - status: 'active' | 'paused' | 'ended' | 'failed' ``` -------------------------------- ### Express Server Setup and Chat Handling with Helix AI SDK Source: https://agents.open-source.onhelix.ai/frontend/frameworks This snippet demonstrates setting up an Express server to handle chat interactions with the Helix AI SDK. It includes CORS configuration, JSON parsing, and defines routes for POST requests (sending messages) and GET requests (streaming responses). It utilizes helper functions from the SDK to pipe responses and handle errors. ```typescript import express from 'express'; import cors from 'cors'; import { createFrontendHandler, FrontendHandlerError } from '@helix-agents/ai-sdk'; import { pipeToExpress, sendErrorToExpress } from '@helix-agents/ai-sdk/adapters/express'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Setup const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); const handler = createFrontendHandler({ streamManager, executor, agent: MyAgent, // Assuming MyAgent is defined elsewhere stateStore, }); // Create app const app = express(); // Middleware app.use( cors({ origin: ['http://localhost:3000'], allowedHeaders: ['Content-Type', 'Last-Event-ID'], exposedHeaders: ['X-Session-Id'], }) ); app.use(express.json()); // Execute agent (POST) app.post('/api/chat', async (req, res) => { try { const { message, messages, state } = req.body; const response = await handler.handleRequest({ method: 'POST', body: { message: message ?? messages?.[messages.length - 1]?.content, state, }, }); // Use helper to pipe response await pipeToExpress(response, res); } catch (error) { if (error instanceof FrontendHandlerError) { sendErrorToExpress(error, res); return; } console.error('Unexpected error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Stream existing execution (GET) app.get('/api/chat/:streamId', async (req, res) => { try { const { streamId } = req.params; const lastEventId = req.get('Last-Event-ID'); const response = await handler.handleRequest({ method: 'GET', streamId, resumeAt: lastEventId ? parseInt(lastEventId) : undefined, }); await pipeToExpress(response, res); } catch (error) { if (error instanceof FrontendHandlerError) { sendErrorToExpress(error, res); return; } console.error('Unexpected error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Load message history app.get('/api/messages/:sessionId', async (req, res) => { try { const { sessionId } = req.params; const offset = parseInt((req.query.offset as string) ?? '0'); const limit = parseInt((req.query.limit as string) ?? '100'); const { messages, hasMore } = await handler.getMessages(sessionId, { offset, limit, }); res.json({ messages, hasMore }); } catch (error) { if (error instanceof FrontendHandlerError) { sendErrorToExpress(error, res); return; } console.error('Unexpected error:', error); res.status(500).json({ error: 'Internal server error' }); } }); app.listen(3001, () => { console.log('Server running on http://localhost:3001'); }); ``` -------------------------------- ### Changeset File Example Source: https://agents.open-source.onhelix.ai/internals/contributing Shows the structure of a generated Changeset Markdown file. This file details the packages affected by the changes, the type of version bump for each, and a summary of the changes. ```markdown --- '@helix-agents/core': minor '@helix-agents/runtime-js': patch --- Add new orchestration function for step processing ``` -------------------------------- ### Complete Helix AI Agent Execution Example Source: https://agents.open-source.onhelix.ai/storage/redis A comprehensive example demonstrating the setup and execution of a Helix AI agent using Redis for state and stream management, and Vercel AI for LLM capabilities. It covers initialization, agent execution, real-time streaming, result retrieval, and cleanup. ```typescript import Redis from 'ioredis'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { RedisStateStore, RedisStreamManager } from '@helix-agents/store-redis'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Setup const redis = new Redis(process.env.REDIS_URL); const stateStore = new RedisStateStore(redis, { prefix: 'myapp:' }); const streamManager = new RedisStreamManager(redis, { prefix: 'myapp:' }); const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); // Execute agent const handle = await executor.execute(ResearchAgent, 'Research AI agents', { sessionId: 'my-session-1', }); // Stream in real-time const stream = await handle.stream(); if (stream) { for await (const chunk of stream) { process.stdout.write(chunk.type === 'text_delta' ? chunk.delta : ''); } } // Get result const result = await handle.result(); console.log('\nResult:', result.output); // Cleanup (optional) await stateStore.deleteSession(handle.sessionId); // Close connection when done await redis.quit(); ``` -------------------------------- ### Documentation Commands - Bash Source: https://agents.open-source.onhelix.ai/internals/contributing Commands to manage documentation for the Helix Agents project using VitePress. These include starting a development server, building for production, and previewing the production build. ```bash npm run docs:dev # Start dev server npm run docs:build # Production build npm run docs:preview # Preview build ``` -------------------------------- ### Run Research Assistant Example (Bash) Source: https://agents.open-source.onhelix.ai/examples/research-assistant Provides bash commands to clone, install dependencies, set the API key, and run the research assistant demo. It also shows how to run the demo with a custom topic. ```bash # Clone and install cd examples/research-assistant npm install # Set your API key export OPENAI_API_KEY=sk-xxx # Run the demo npm run demo # Or with a custom topic npm run demo "quantum computing applications" ``` -------------------------------- ### Create Source Files for New Package - TypeScript Source: https://agents.open-source.onhelix.ai/internals/contributing Example TypeScript file for the entry point of a new package. This demonstrates a simple exported function `myFunction` that returns a string. ```typescript // packages/my-package/src/index.ts export function myFunction() { return 'hello'; } ``` -------------------------------- ### JSAgentExecutor Usage Example in TypeScript Source: https://agents.open-source.onhelix.ai/reference/runtime-js A comprehensive example demonstrating the setup and execution of a JSAgentExecutor. It includes defining a simple agent with a tool, configuring the executor with in-memory stores and an AI adapter, executing the agent, streaming results, and retrieving the final output. ```typescript import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; import { defineAgent, defineTool } from '@helix-agents/core'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; // Define agent const MyAgent = defineAgent({ name: 'my-agent', systemPrompt: 'You are a helpful assistant.', outputSchema: z.object({ response: z.string() }), tools: [ defineTool({ name: 'greet', description: 'Generate a greeting', inputSchema: z.object({ name: z.string() }), outputSchema: z.object({ greeting: z.string() }), execute: async ({ name }) => ({ greeting: `Hello, ${name}!` }), }), ], llmConfig: { model: openai('gpt-4o-mini') }, }); // Create executor const executor = new JSAgentExecutor( new InMemoryStateStore(), new InMemoryStreamManager(), new VercelAIAdapter() ); // Execute agent const handle = await executor.execute(MyAgent, 'Greet John'); // Stream results for await (const chunk of (await handle.stream()) ?? []) { if (chunk.type === 'text_delta') { process.stdout.write(chunk.delta); } } // Get final result const result = await handle.result(); console.log('\nOutput:', result.output); ``` -------------------------------- ### Start Agent Execution Request Example (TypeScript) Source: https://agents.open-source.onhelix.ai/runtimes/cloudflare-do Provides a TypeScript example of making a POST request to the '/start' endpoint to initiate agent execution. It demonstrates how to structure the request body with `agentType`, `input`, and `sessionId`. ```typescript // Request const response = await stub.fetch('/start', { method: 'POST', body: JSON.stringify({ agentType: 'researcher', // Agent type from registry input: { message: 'Hello' }, // Input message sessionId: 'session-123', // Session ID for conversation continuity userId: 'user-456', // Optional: user context tags: ['test'], // Optional: tags metadata: { key: 'value' }, // Optional: metadata }), }); // Response interface AgentStartResponse { sessionId: string; streamId: string; status: 'started' | 'resumed'; } ``` -------------------------------- ### Basic FrontendHandler Setup Source: https://agents.open-source.onhelix.ai/frontend/ai-sdk Provides a basic setup for the `FrontendHandler`, showing optional parameters like `stateStore`, `transformerOptions`, and `logger`. ```typescript import { createFrontendHandler } from '@helix-agents/ai-sdk'; const handler = createFrontendHandler({ streamManager, executor, agent: MyAgent, stateStore, // Optional: for getMessages() transformerOptions: { ... }, // Optional: customize transformation logger: console, // Optional: debug logging }); ``` -------------------------------- ### Worker Setup with @helix-agents/store-cloudflare Source: https://agents.open-source.onhelix.ai/reference/store-cloudflare A complete `worker.ts` example demonstrating how to set up a Cloudflare Worker using the @helix-agents/store-cloudflare library. It includes running migrations, creating stores, and handling incoming requests. ```typescript import { createCloudflareStore, StreamServer, runMigration } from '@helix-agents/store-cloudflare'; // Re-export Durable Object export { StreamServer }; interface Env { AGENT_DB: D1Database; STREAMS: DurableObjectNamespace; } export default { async fetch(request: Request, env: Env) { // Run migration on first request (or use scheduled task) await runMigration(env.AGENT_DB); // Create stores const { stateStore, streamManager } = createCloudflareStore({ db: env.AGENT_DB, streams: env.STREAMS, }); // Use stores... const state = await stateStore.loadState('session-123'); return Response.json({ state }); }, }; ``` -------------------------------- ### Usage Example Source: https://agents.open-source.onhelix.ai/reference/store-memory Illustrates a basic usage example of the JSAgentExecutor, including setting up stores, executing an agent, and retrieving the result. ```APIDOC ## Usage Example ### Description Demonstrates how to initialize and execute an agent using `JSAgentExecutor` with in-memory stores and an LLM adapter. ### Request Example ```typescript import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Create stores const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); // Create executor const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); // Execute agent const handle = await executor.execute(MyAgent, 'Hello'); const result = await handle.result(); // Inspect stored state (for debugging) const state = stateStore.getSync(handle.sessionId); const chunks = streamManager.getChunksSync(handle.streamId); ``` ``` -------------------------------- ### Simplify Express Routes with Helix AI SDK Middleware Source: https://agents.open-source.onhelix.ai/frontend/frameworks This snippet shows how to use the `createExpressMiddleware` helper from the Helix AI SDK to simplify the Express route definitions. This middleware abstracts the request handling logic, making the route setup more concise. ```typescript import { createExpressMiddleware } from '@helix-agents/ai-sdk/adapters/express'; // Assuming 'handler' is already created as in the previous example const chatMiddleware = createExpressMiddleware(handler, (req) => ({ method: req.method as 'GET' | 'POST', streamId: req.params.streamId, resumeAt: req.get('Last-Event-ID') ? parseInt(req.get('Last-Event-ID')!) : undefined, body: req.body?.message ? { message: req.body.message, state: req.body.state } : undefined, })); app.post('/api/chat', chatMiddleware); app.get('/api/chat/:streamId', chatMiddleware); ``` -------------------------------- ### Run Basic Research Assistant Example (JavaScript) Source: https://agents.open-source.onhelix.ai/examples Demonstrates a basic agent with tools, state, and streaming capabilities using the JS runtime. This example is suitable for local development and testing. ```bash # Clone and setup git clone https://github.com/your-org/helix-agents.git cd helix-agents npm install npm run build # Run JS example cd examples/research-assistant npm test # Run tests (no API key needed) OPENAI_API_KEY=sk-xxx npm run demo # Run with real LLM ``` -------------------------------- ### Install Dependencies (Bash) Source: https://agents.open-source.onhelix.ai/examples/opennext-cloudflare-do Installs project dependencies using npm. This is a prerequisite for running the project locally. ```bash # Install dependencies npm install ``` -------------------------------- ### Backend Setup for Frontend Integration Source: https://agents.open-source.onhelix.ai/frontend Sets up the backend for frontend integration by creating necessary components like state stores, stream managers, executors, and the frontend handler. This example uses in-memory stores and a Vercel AI Adapter. ```typescript import { createFrontendHandler } from '@helix-agents/ai-sdk'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Create stores and executor const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); // Create frontend handler const handler = createFrontendHandler({ streamManager, executor, agent: MyAgent, stateStore, // Optional: for getMessages() }); // Use with your framework // See Framework Examples for Express, Hono, etc. ``` -------------------------------- ### Define a Web Search Tool for Helix Agents Source: https://agents.open-source.onhelix.ai/guide/getting-started Creates a reusable tool for the Helix Agent that allows it to search the web. This tool includes input and output schemas for the search query and results, respectively. The `execute` function provides a mock implementation for demonstration purposes. ```typescript import { defineTool } from '@helix-agents/sdk'; import { z } from 'zod'; const searchTool = defineTool({ name: 'search', description: 'Search the web for information on a topic', // What the LLM provides when calling this tool inputSchema: z.object({ query: z.string().describe('The search query'), }), // What the tool returns outputSchema: z.object({ results: z.array( z.object({ title: z.string(), url: z.string(), snippet: z.string(), }) ), }), // The actual implementation execute: async ({ query }, context) => { // In a real app, you'd call a search API // For now, we'll return mock results console.log(`Searching for: ${query}`); return { results: [ { title: `${query} - Wikipedia`, url: `https://en.wikipedia.org/wiki/${encodeURIComponent(query)}`, snippet: `Learn about ${query} and its various aspects...`, }, { title: `Understanding ${query}`, url: `https://example.com/${encodeURIComponent(query)}`, snippet: `A comprehensive guide to ${query}...`, }, ], }; }, }); ``` -------------------------------- ### Install @helix-agents/ai-sdk Source: https://agents.open-source.onhelix.ai/reference/ai-sdk Installs the @helix-agents/ai-sdk package using npm. This is the first step to integrate Helix Agents with the Vercel AI SDK. ```bash npm install @helix-agents/ai-sdk ``` -------------------------------- ### MockLLMAdapter Initialization and Usage in Tests Source: https://agents.open-source.onhelix.ai/llm/custom Demonstrates how to create and use MockLLMAdapter for testing AI agents. It shows pre-configuration of responses, incremental addition of responses, and verification of call counts. ```typescript import { MockLLMAdapter } from '@helix-agents/core'; // Create with pre-configured responses const mock = new MockLLMAdapter([ { type: 'text', content: 'Searching...', shouldStop: false }, { type: 'tool_calls', toolCalls: [{ id: 'tc1', name: 'search', arguments: { query: 'AI' } }], }, { type: 'structured_output', output: { result: 'Found it!' } }, ]); // Or add responses incrementally mock.addResponse({ type: 'text', content: 'Hello', shouldStop: true }); // Use in tests const executor = new JSAgentExecutor(stateStore, streamManager, mock); const handle = await executor.execute(agent, 'Test'); const result = await handle.result(); // Verify call count expect(mock.getCallCount()).toBe(3); ``` -------------------------------- ### Complete Chat Agent Example with Hono Source: https://agents.open-source.onhelix.ai/frontend/ai-sdk This example demonstrates how to set up a complete chat agent using the Helix Agents AI SDK. It includes defining the agent, creating an executor with memory stores and an adapter, and integrating it with a Hono web server for handling chat requests and restoring conversation history. Dependencies include '@helix-agents/ai-sdk', '@helix-agents/runtime-js', '@helix-agents/store-memory', '@helix-agents/llm-vercel', '@helix-agents/core', '@ai-sdk/openai', 'zod', and 'hono'. ```typescript import { createFrontendHandler, FrontendHandlerError } from '@helix-agents/ai-sdk'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; import { defineAgent } from '@helix-agents/core'; import { openai } from '@ai-sdk/openai'; import { z } from 'zod'; // Define agent const ChatAgent = defineAgent({ name: 'chat', systemPrompt: 'You are a helpful assistant.', outputSchema: z.object({ response: z.string(), }), llmConfig: { model: openai('gpt-4o'), }, }); // Create executor const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); // Create handler const handler = createFrontendHandler({ streamManager, executor, agent: ChatAgent, stateStore, }); // Use with Hono import { Hono } from 'hono'; const app = new Hono(); app.post('/api/chat', async (c) => { try { const body = await c.req.json(); const response = await handler.handleRequest({ method: 'POST', body: { message: body.message }, }); return new Response(response.body, { status: response.status, headers: response.headers, }); } catch (error) { if (error instanceof FrontendHandlerError) { return c.json({ error: error.message, code: error.code }, error.statusCode); } throw error; } }); // Load messages for conversation restore app.get('/api/messages/:sessionId', async (c) => { const sessionId = c.req.param('sessionId'); const { messages, hasMore } = await handler.getMessages(sessionId); return c.json({ messages, hasMore }); }); ``` -------------------------------- ### Basic Setup Source: https://agents.open-source.onhelix.ai/runtimes/js Set up the JSAgentExecutor with necessary stores and an LLM adapter. ```APIDOC ## Basic Setup ```typescript import { JSAgentExecutor, InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/sdk'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Create stores const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const llmAdapter = new VercelAIAdapter(); // Create executor const executor = new JSAgentExecutor(stateStore, streamManager, llmAdapter); ``` ``` -------------------------------- ### Express Middleware Helper Source: https://agents.open-source.onhelix.ai/frontend/frameworks Demonstrates using the `createExpressMiddleware` helper for a more concise way to handle chat requests and streaming. ```APIDOC ## Express Middleware Helper ### Description Utilizes the `createExpressMiddleware` function from `@helix-agents/ai-sdk/adapters/express` to simplify the Express route handlers for chat interactions. ### Method POST, GET ### Endpoint /api/chat, /api/chat/:streamId ### Parameters #### Request Body (for POST) - **message** (string) - Required - The user's message content. - **state** (object) - Optional - The current state of the conversation. #### Path Parameters (for GET) - **streamId** (string) - Required - The unique identifier for the stream to resume. #### Headers (for GET) - **Last-Event-ID** (string) - Optional - The ID of the last event received, used to resume the stream. ### Request Example ```typescript import { createExpressMiddleware } from '@helix-agents/ai-sdk/adapters/express'; const chatMiddleware = createExpressMiddleware(handler, (req) => ({ method: req.method as 'GET' | 'POST', streamId: req.params.streamId, resumeAt: req.get('Last-Event-ID') ? parseInt(req.get('Last-Event-ID')!) : undefined, body: req.body?.message ? { message: req.body.message, state: req.body.state } : undefined, })); app.post('/api/chat', chatMiddleware); app.get('/api/chat/:streamId', chatMiddleware); ``` ### Response #### Success Response (200) Streams the AI's response back to the client. #### Error Response (500) - **error** (string) - Description of the internal server error. ``` -------------------------------- ### Create JS Agent Executor with In-Memory Stores (TypeScript) Source: https://agents.open-source.onhelix.ai/guide/getting-started This snippet demonstrates how to create a JavaScript agent executor using in-memory stores for state persistence and stream management. It utilizes the Vercel AI SDK as an LLM adapter. This setup is suitable for development environments. ```typescript import { JSAgentExecutor, InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/sdk'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // State store: where agent state persists between steps const stateStore = new InMemoryStateStore(); // Stream manager: handles real-time event streaming const streamManager = new InMemoryStreamManager(); // LLM adapter: bridges to the Vercel AI SDK const llmAdapter = new VercelAIAdapter(); // Create the executor const executor = new JSAgentExecutor(stateStore, streamManager, llmAdapter); ``` -------------------------------- ### Get Agent Status Request Example (TypeScript) Source: https://agents.open-source.onhelix.ai/runtimes/cloudflare-do Shows a TypeScript example of making a GET request to the '/status' endpoint to retrieve the current execution status of an agent. It includes the expected `AgentStatusResponse` interface. ```typescript const response = await stub.fetch('/status'); const status = await response.json(); interface AgentStatusResponse { sessionId: string | null; status: string; // 'active' | 'completed' | 'failed' | 'paused' | 'interrupted' stepCount: number; output?: unknown; error?: string; checkpointId?: string; isExecuting: boolean; // true if currently running } ``` -------------------------------- ### Clone and Install Dependencies - Bash Source: https://agents.open-source.onhelix.ai/internals/contributing Clones the Helix Agents repository and installs project dependencies using npm. Ensure Node.js and npm are installed and meet the version requirements. ```bash git clone https://github.com/your-org/helix-agents.git cd helix-agents npm install ``` -------------------------------- ### Custom Runtime Implementation with Helix Core Functions Source: https://agents.open-source.onhelix.ai/internals/architecture Demonstrates how to implement a custom agent execution runtime by leveraging pure orchestration functions from the '@helix-agents/core' library. This example shows the initialization of agent state and the basic structure for an execution loop. ```typescript import { initializeAgentState, buildMessagesForLLM, buildEffectiveTools, planStepProcessing, shouldStopExecution, } from '@helix-agents/core'; // Implement AgentExecutor interface class MyCustomRuntime implements AgentExecutor { async execute(agent, input) { // Use orchestration functions const state = initializeAgentState({ agent, input, runId, streamId }); // ... execution loop } } ``` -------------------------------- ### ToolStartChunk Interface and Example Source: https://agents.open-source.onhelix.ai/internals/stream-protocol Represents the start of a tool invocation. It includes 'type', 'toolCallId', 'toolName', 'arguments', 'agentId', optional 'agentType', and 'timestamp'. An example illustrates its JSON structure. ```typescript interface ToolStartChunk { type: 'tool_start'; toolCallId: string; // Unique ID from LLM toolName: string; // Tool name arguments: unknown; // Tool input arguments agentId: string; agentType?: string; timestamp: number; } ``` ```json { "type": "tool_start", "toolCallId": "call_xyz789", "toolName": "web_search", "arguments": { "query": "TypeScript tutorials" }, "agentId": "run-abc123", "timestamp": 1702329600000 } ``` -------------------------------- ### Unit Test Example - TypeScript Source: https://agents.open-source.onhelix.ai/internals/contributing An example of a unit test for the `planStepProcessing` function using Vitest. It demonstrates testing a function that handles text responses and asserts the expected output structure. ```typescript // packages/core/src/__tests__/step-processor.test.ts import { describe, it, expect } from 'vitest'; import { planStepProcessing } from '../orchestration/step-processor.js'; describe('planStepProcessing', () => { it('handles text response', () => { const plan = planStepProcessing({ type: 'text', content: 'Hello', shouldStop: false, }); expect(plan.isTerminal).toBe(false); expect(plan.assistantMessagePlan?.content).toBe('Hello'); }); }); ``` -------------------------------- ### Basic Redis Connection Setup Source: https://agents.open-source.onhelix.ai/storage/redis Establishes a basic connection to a local Redis instance using `ioredis` and initializes `RedisStateStore` and `RedisStreamManager`. This setup is the foundation for using Redis for agent state and streams. ```typescript import Redis from 'ioredis'; import { RedisStateStore, RedisStreamManager } from '@helix-agents/store-redis'; // Create Redis client const redis = new Redis({ host: 'localhost', port: 6379, // password: 'your-password', // tls: {}, // For Redis Cloud/AWS ElastiCache }); // Create stores const stateStore = new RedisStateStore(redis); const streamManager = new RedisStreamManager(redis); ``` -------------------------------- ### Get Agent History Request Example (TypeScript) Source: https://agents.open-source.onhelix.ai/runtimes/cloudflare-do Provides a TypeScript example for fetching historical stream chunks from the '/history' endpoint using query parameters for sequence and limit. It outlines the structure of the response. ```typescript const response = await stub.fetch('/history?fromSequence=0&limit=100'); const history = await response.json<{ chunks: Array<{ sequence: number; chunk: StreamChunk }>; hasMore: boolean; latestSequence: number; }>(); ``` -------------------------------- ### Monitoring Log Example (TypeScript) Source: https://agents.open-source.onhelix.ai/examples/research-assistant-cloudflare An example of structured logging for monitoring agent execution. It logs information such as the log level, run ID, agent type, action being performed (e.g., 'start'), and a timestamp, formatted as JSON. ```typescript console.log( JSON.stringify({ level: 'info', runId, agentType: agent.name, action: 'start', timestamp: new Date().toISOString(), }) ); ``` -------------------------------- ### Streaming Callbacks Implementation Source: https://agents.open-source.onhelix.ai/llm/custom Example of implementing the `generateStep` method to utilize streaming callbacks for real-time updates. It demonstrates how to stream text tokens, thinking content, tool calls, and report errors. ```typescript async generateStep(input: LLMGenerateInput): Promise> { const { callbacks } = input; // Stream text tokens for await (const token of provider.streamTokens()) { callbacks?.onTextDelta?.(token); } // Stream thinking content if (thinkingChunk) { callbacks?.onThinking?.(thinkingChunk, isComplete); } // Notify of tool calls for (const toolCall of toolCalls) { callbacks?.onToolCall?.(toolCall); } // Report errors if (error) { callbacks?.onError?.(error); } return result; } ``` -------------------------------- ### Quick Start: Enable Usage Tracking in Agent Execution Source: https://agents.open-source.onhelix.ai/guide/usage-tracking Demonstrates how to pass a `UsageStore` instance when executing an agent to enable tracking of token consumption, tool executions, and other metrics. It shows how to retrieve aggregated usage data after the agent run. ```typescript import { JSAgentExecutor, defineAgent } from '@helix-agents/sdk'; import { InMemoryUsageStore } from '@helix-agents/store-memory'; // Create stores const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const usageStore = new InMemoryUsageStore(); // Create executor const executor = new JSAgentExecutor(stateStore, streamManager, llmAdapter); // Execute with usage tracking const handle = await executor.execute(agent, 'Analyze this data', { usageStore }); // Wait for completion await handle.result(); // Get aggregated usage const rollup = await handle.getUsageRollup(); console.log(`Total tokens: ${rollup.tokens.total}`); console.log(`Tool calls: ${rollup.toolStats.totalCalls}`); ``` -------------------------------- ### Testing Patterns with MockLLMAdapter Source: https://agents.open-source.onhelix.ai/llm/custom Illustrates common testing patterns using MockLLMAdapter, including setting up mock responses for sequential LLM interactions (tool calls followed by structured output) and handling error scenarios. ```typescript import { describe, it, expect, beforeEach } from 'vitest'; import { MockLLMAdapter } from '@helix-agents/core'; describe('MyAgent', () => { let mock: MockLLMAdapter; beforeEach(() => { mock = new MockLLMAdapter(); }); it('should use tools correctly', async () => { // First step: LLM requests tool mock.addResponse({ type: 'tool_calls', toolCalls: [{ id: 'tc1', name: 'lookup', arguments: { id: '123' } }], }); // Second step: LLM completes with output mock.addResponse({ type: 'structured_output', output: { status: 'success', data: 'Found' }, }); const result = await executor.execute(agent, 'Look up item 123'); expect(result.output).toEqual({ status: 'success', data: 'Found' }); }); it('should handle errors', async () => { mock.addResponse({ type: 'error', message: 'API unavailable', recoverable: false, }); const result = await executor.execute(agent, 'Test'); expect(result.status).toBe('failed'); }); }); ``` -------------------------------- ### GET /api/messages/:sessionId - Load Message History Source: https://agents.open-source.onhelix.ai/frontend/frameworks Retrieves the message history for a given session. Supports pagination using `offset` and `limit` query parameters. ```APIDOC ## GET /api/messages/:sessionId ### Description Retrieves message history for a specific session, with support for pagination. ### Method GET ### Endpoint /api/messages/:sessionId ### Parameters #### Path Parameters - **sessionId** (string) - Required - The unique identifier for the session. #### Query Parameters - **offset** (integer) - Optional - The number of messages to skip (defaults to 0). - **limit** (integer) - Optional - The maximum number of messages to return (defaults to 100). ### Response #### Success Response (200) - **messages** (array) - An array of message objects. - **hasMore** (boolean) - Indicates if there are more messages available. #### Response Example ```json { "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hi there!" } ], "hasMore": true } ``` #### Error Response (500) - **error** (string) - Description of the internal server error. ``` -------------------------------- ### Set Up Environment Variables (Bash) Source: https://agents.open-source.onhelix.ai/examples/opennext-cloudflare-do Configures environment variables for local development by creating a .env file and setting the OPENAI_API_KEY. This ensures the application has the necessary API keys. ```bash # Set up environment (symlinks to root .env) echo "OPENAI_API_KEY=sk-..." >> ../../.env ``` -------------------------------- ### Previous FrontendHandler Setup (TypeScript) Source: https://agents.open-source.onhelix.ai/migration/v0.15-cloudflare-frontend-handler Illustrates the older method of setting up the FrontendHandler before v0.15, which involved manually creating and passing a DOClient. This method is now deprecated. ```typescript import { createFrontendHandler } from '@helix-agents/ai-sdk'; import { DOClient } from '@helix-agents/ai-sdk/cloudflare'; const stub = getDOStub(sessionId); const client = new DOClient({ baseUrl: 'https://do', fetch: (url, init) => stub.fetch(url, init), routePattern: () => '', }); const handler = createFrontendHandler({ client, agentName: 'chat-agent', }); ``` -------------------------------- ### Hono HTTP Framework Integration (TypeScript) Source: https://agents.open-source.onhelix.ai/frontend/frameworks Integrates Helix Agents with the Hono web framework using standard Web APIs. This example sets up CORS, handles agent requests for chat completion via POST, streams existing executions via GET, and retrieves message history. It includes error handling for `FrontendHandlerError`. ```typescript import { Hono } from 'hono'; import { cors } from 'hono/cors'; import { createFrontendHandler, FrontendHandlerError } from '@helix-agents/ai-sdk'; import { JSAgentExecutor } from '@helix-agents/runtime-js'; import { InMemoryStateStore, InMemoryStreamManager } from '@helix-agents/store-memory'; import { VercelAIAdapter } from '@helix-agents/llm-vercel'; // Setup const stateStore = new InMemoryStateStore(); const streamManager = new InMemoryStreamManager(); const executor = new JSAgentExecutor(stateStore, streamManager, new VercelAIAdapter()); const handler = createFrontendHandler({ streamManager, executor, agent: MyAgent, stateStore, }); // Create app const app = new Hono(); // CORS for frontend app.use( '/api/*', cors({ origin: ['http://localhost:3000'], allowHeaders: ['Content-Type', 'Last-Event-ID'], exposeHeaders: ['X-Session-Id'], }) ); // Execute agent (POST) app.post('/api/chat', async (c) => { try { const body = await c.req.json(); const response = await handler.handleRequest({ method: 'POST', body: { message: body.message ?? body.messages?.[body.messages.length - 1]?.content, state: body.state, }, }); return new Response(response.body, { status: response.status, headers: response.headers, }); } catch (error) { if (error instanceof FrontendHandlerError) { return c.json( { error: error.message, code: error.code }, error.statusCode as 400 | 404 | 410 | 500 | 501 ); } throw error; } }); // Stream existing execution (GET) app.get('/api/chat/:streamId', async (c) => { try { const streamId = c.req.param('streamId'); const lastEventId = c.req.header('Last-Event-ID'); const response = await handler.handleRequest({ method: 'GET', streamId, resumeAt: lastEventId ? parseInt(lastEventId) : undefined, }); return new Response(response.body, { status: response.status, headers: response.headers, }); } catch (error) { if (error instanceof FrontendHandlerError) { return c.json( { error: error.message, code: error.code }, error.statusCode as 400 | 404 | 410 | 500 | 501 ); } throw error; } }); // Load message history app.get('/api/messages/:sessionId', async (c) => { try { const sessionId = c.req.param('sessionId'); const offset = parseInt(c.req.query('offset') ?? '0'); const limit = parseInt(c.req.query('limit') ?? '100'); const { messages, hasMore } = await handler.getMessages(sessionId, { offset, limit, }); return c.json({ messages, hasMore }); } catch (error) { if (error instanceof FrontendHandlerError) { return c.json( { error: error.message, code: error.code }, error.statusCode as 400 | 404 | 410 | 500 | 501 ); } throw error; } }); export default app; ``` -------------------------------- ### Get Messages with Specific Metadata Key (TypeScript) Source: https://agents.open-source.onhelix.ai/reference/core Illustrates how to retrieve all messages from an array that contain a specific metadata key using the `getMessagesWithMetadataKey` function. This example retrieves messages that have the 'source' metadata key. ```typescript const messagesWithSource = getMessagesWithMetadataKey(messages, 'source'); ``` -------------------------------- ### Cloudflare Workers API Endpoints Source: https://agents.open-source.onhelix.ai/frontend/frameworks This section details the API endpoints for the Cloudflare Workers implementation, including POST /api/chat for sending messages and GET /api/chat/:streamId for retrieving stream data. ```APIDOC ## POST /api/chat ### Description Handles incoming chat messages via POST requests. It processes the message and state, then returns the agent's response. ### Method POST ### Endpoint /api/chat ### Parameters #### Request Body - **message** (string) - Required - The user's chat message. - **state** (object) - Optional - The current state of the conversation. ### Request Example ```json { "message": "What is the weather like today?", "state": { "location": "New York" } } ``` ### Response #### Success Response (200) - **body** (any) - The agent's response body. - **status** (number) - The HTTP status code. - **headers** (Headers) - Response headers, including CORS headers. #### Response Example ```json { "response": "The weather today is sunny with a high of 75 degrees Fahrenheit." } ``` ## GET /api/chat/:streamId ### Description Retrieves streaming data for a specific chat session using the stream ID. Supports resuming streams using the `Last-Event-ID` header. ### Method GET ### Endpoint /api/chat/:streamId ### Parameters #### Path Parameters - **streamId** (string) - Required - The unique identifier for the chat stream. #### Headers - **Last-Event-ID** (string) - Optional - The ID of the last event received, used for resuming streams. ### Response #### Success Response (200) - **body** (ReadableStream | string) - The stream data or response body. - **status** (number) - The HTTP status code. - **headers** (Headers) - Response headers, including CORS headers. #### Response Example (Response will be a stream of Server-Sent Events) #### Error Response (e.g., 400, 500) - **error** (string) - A message describing the error. - **code** (string) - An error code. #### Error Response Example ```json { "error": "Stream not found.", "code": "STREAM_NOT_FOUND" } ``` ```