🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More
Socket
Book a DemoSign in
Socket

honidev

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

honidev

[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

latest
npmnpm
Version
0.5.6
Version published
Weekly downloads
148
4833.33%
Maintainers
1
Weekly downloads
 
Created
Source

Honi

MIT License

Edge-first AI agents for Cloudflare Workers.

The Mastra for developers who deploy on Cloudflare.

Honi is a lightweight framework for building agentic AI applications on Cloudflare Workers. It combines Hono for routing, Durable Objects for persistent memory, and the Vercel AI SDK for multi-provider LLM support — all in a single createAgent() call.

Quick Start

Install

bun add honidev

Create an Agent

// src/index.ts
import { createAgent, tool, z } from 'honidev';

const searchCRM = tool({
  name: 'search_crm',
  description: 'Search HubSpot for deal info',
  input: z.object({ query: z.string() }),
  handler: async ({ query }) => {
    // Your CRM logic here
    return { results: [] };
  },
});

const salesCoach = createAgent({
  name: 'sales-coach',
  model: 'claude-sonnet-4-5',
  memory: { enabled: true },
  tools: [searchCRM],
  system: 'You are a real-time sales coach.',
  binding: 'SALES_COACH_DO',
});

export default { fetch: salesCoach.fetch };
export const SalesCoachDO = salesCoach.DurableObject;

Configure Wrangler

# wrangler.toml
name = "sales-coach-agent"
main = "src/index.ts"
compatibility_date = "2024-12-01"

[[durable_objects.bindings]]
name = "SALES_COACH_DO"
class_name = "SalesCoachDO"

[[migrations]]
tag = "v1"
new_classes = ["SalesCoachDO"]

Deploy

wrangler deploy

Chat with Your Agent

curl -X POST https://your-worker.workers.dev/chat \
  -H "Content-Type: application/json" \
  -H "X-Thread-Id: thread-123" \
  -d '{"message": "What deals are closing this week?"}'

Memory (Phase 2)

Honi supports four tiers of memory, all opt-in:

TierBackingSurvives DO eviction?Queryable across threads?
WorkingDurable Object storageNoNo
EpisodicD1YesYes
SemanticVectorize + Workers AIYesYes (similarity search)
Graphedgraph (DO)YesYes (entity/relationship traversal)

Setup

Add bindings to your wrangler.toml:

[[d1_databases]]
binding = "DB"
database_name = "honi-memory"
database_id = "YOUR_DB_ID"

[[vectorize]]
binding = "VECTORIZE"
index_name = "honi-semantic"
dimensions = 768
metric = "cosine"

[ai]
binding = "AI"

# Graph memory — deploy edgraph and add a service binding (or use urlEnvVar for HTTP)
[[services]]
binding = "EDGRAPH"
service = "edgraph"

Run the D1 migration:

wrangler d1 migrations apply honi-memory

Configure

const agent = createAgent({
  name: 'my-agent',
  model: 'claude-sonnet-4-5',
  memory: {
    enabled: true,
    episodic: { enabled: true },
    semantic: { enabled: true, topK: 3 },
    graph: {
      enabled: true,
      graphId: 'my-knowledge-base',
      binding: 'EDGRAPH',       // CF service binding (preferred)
      // urlEnvVar: 'EDGRAPH_URL', // or HTTP URL via env var
      apiKeyEnvVar: 'EDGRAPH_API_KEY',
      contextDepth: 1,          // hop depth for context expansion
    },
  },
  system: 'You are a helpful assistant.',
});

All tiers are fully opt-in. Missing bindings log a warning and fall back gracefully.

How it works

  • On each request: past messages load from D1 (episodic), the user message is embedded and searched against Vectorize (semantic), and any entity IDs found in semantic results are expanded via graph traversal. All context is prepended to the system prompt.
  • After each response: the conversation turn is saved to D1 and both user + assistant messages are embedded and upserted to Vectorize for future retrieval.

Graph memory — writing entities from tools

Graph memory is most powerful when tools write entities as they discover them:

import { tool, GraphMemory } from 'honidev';

const myTool = tool({
  name: 'lookup_customer',
  description: 'Look up a customer by ID',
  input: z.object({ customerId: z.string() }),
  handler: async (input, ctx) => {
    const customer = await db.getCustomer(input.customerId);

    // Write to graph — ctx.graph is the live GraphMemory instance
    if (ctx?.graph && customer) {
      await ctx.graph.upsertNode(customer.id, 'Customer', {
        name: customer.name,
        plan: customer.plan,
      });
      if (customer.accountManagerId) {
        await ctx.graph.upsertEdge(
          customer.id,
          customer.accountManagerId,
          'managed_by',
        );
      }
    }

    return customer;
  },
});

ctx.graph is the live GraphMemory instance bound to the current agent. Entities written here are immediately available for future context retrieval.

Using GraphMemory standalone

GraphMemory can also be used outside of an agent — as a shared knowledge base across multiple services:

import { GraphMemory } from 'honidev';

const graph = new GraphMemory({
  graphId: 'crm',
  url: 'https://edgraph.myapp.workers.dev',
  apiKey: process.env.EDGRAPH_API_KEY,
});

await graph.upsertNode('alice', 'Person', { role: 'CTO', company: 'ACME' });
await graph.upsertNode('acme', 'Company', { industry: 'SaaS' });
await graph.upsertEdge('alice', 'acme', 'works_at');

// Get context block for LLM injection
const context = await graph.toContext(['alice'], 2);
// "[Knowledge graph context:]
//  - (Person:alice) {role="CTO", company="ACME"}
//    → [works_at] → (Company:acme)
//  [End graph context]"

// Traversal
const path = await graph.shortestPath('alice', 'bob');
const neighbours = await graph.getNeighbours('alice', 'out', ['manages']);

Core Concepts

Agents

An agent is created with createAgent() and bundles:

  • A Hono-powered HTTP API with /chat, /history routes
  • A Durable Object class for persistent, per-thread state
  • An LLM connection with automatic tool-calling loops and streaming

Tools

Define tools with Zod schemas. Honi auto-generates the JSON schema for the LLM and validates inputs at runtime:

const weatherTool = tool({
  name: 'get_weather',
  description: 'Get current weather for a city',
  input: z.object({
    city: z.string().describe('City name'),
    units: z.enum(['celsius', 'fahrenheit']).default('celsius'),
  }),
  handler: async ({ city, units }) => {
    return { temp: 22, city, units };
  },
});

Memory

When memory: { enabled: true }, conversation history is persisted in Durable Object storage. Each thread (identified by X-Thread-Id header) gets its own isolated memory.

  • POST /chat — send a message, get a streaming response
  • GET /history?threadId=xxx — retrieve conversation history
  • DELETE /history?threadId=xxx — clear a thread's history

Supported Models

Honi uses the Vercel AI SDK under the hood. Model routing is automatic based on the model ID prefix:

Model prefixProviderEnv var / bindingExample model
claude-*AnthropicANTHROPIC_API_KEYclaude-sonnet-4-5
gpt-*, o1, o3-*OpenAIOPENAI_API_KEYgpt-4o, o3-mini
gemini-*GoogleGOOGLE_AI_API_KEYgemini-2.5-flash-preview
groq/*GroqGROQ_API_KEYgroq/llama-3.3-70b-versatile
deepseek-*DeepSeekDEEPSEEK_API_KEYdeepseek-chat, deepseek-reasoner
mistral-*, codestral-*, pixtral-*MistralMISTRAL_API_KEYmistral-large-latest
grok-*xAIXAI_API_KEYgrok-3, grok-3-mini
sonar*, perplexity/*PerplexityPERPLEXITY_API_KEYsonar-pro, sonar-reasoning
together/*Together AITOGETHER_API_KEYtogether/meta-llama/Llama-3.3-70B-Instruct-Turbo
command-*CohereCOHERE_API_KEYcommand-r-plus, command-a-03-2025
azure/*Azure OpenAIAZURE_OPENAI_API_KEY + AZURE_OPENAI_ENDPOINTazure/gpt-4o
@cf/*Workers AIAI binding in wrangler.toml@cf/meta/llama-3.1-8b-instruct

All non-core providers use optional peer dependencies — zero bundle cost unless installed. Set API keys as Cloudflare Worker secrets:

wrangler secret put ANTHROPIC_API_KEY
wrangler secret put GOOGLE_AI_API_KEY
# etc.

Non-Anthropic/OpenAI/Google providers require their AI SDK package:

npm install @ai-sdk/groq       # Groq
npm install @ai-sdk/deepseek   # DeepSeek
npm install @ai-sdk/mistral    # Mistral
npm install @ai-sdk/xai        # xAI
npm install @ai-sdk/perplexity # Perplexity
npm install @ai-sdk/togetherai # Together AI
npm install @ai-sdk/cohere     # Cohere
npm install @ai-sdk/azure      # Azure OpenAI
npm install @ai-sdk/cloudflare # Workers AI

Workers AI

Use any Workers AI model by prefixing with @cf/:

# wrangler.toml
[ai]
binding = "AI"
const agent = createAgent({
  name: 'my-agent',
  model: '@cf/meta/llama-3.1-8b-instruct',  // Uses Workers AI
  system: 'You are a helpful assistant.',
});

Workers AI support requires the optional @ai-sdk/cloudflare package:

npm install @ai-sdk/cloudflare

AI Gateway

Route all LLM calls through Cloudflare AI Gateway for logging, rate limiting, and caching at the edge:

const agent = createAgent({
  name: 'my-agent',
  model: 'claude-sonnet-4-5',
  observability: {
    aiGateway: {
      accountId: 'your-account-id',
      gatewayId: 'your-gateway-id',
    },
  },
  system: 'You are a helpful assistant.',
});
// All LLM calls now route through CF AI Gateway for observability

Streaming

All responses stream via the AI SDK data protocol, compatible with the useChat() hook from ai/react:

import { useChat } from 'ai/react';

const { messages, input, handleSubmit } = useChat({
  api: 'https://your-worker.workers.dev/chat',
  headers: { 'X-Thread-Id': 'thread-123' },
});

Comparison

FeatureHoniMastraLangChain
RuntimeCloudflare WorkersNode.jsNode.js
MemoryDurable ObjectsPostgres / RedisVarious
StreamingSSE (AI SDK)SSECallbacks
Deploywrangler deploySelf-hostSelf-host
Cold start~0 ms (edge)SecondsSeconds
Bundle sizeMinimalHeavyHeavy
Tool systemZod-nativeZod-nativeMixed
FrameworkHonoExpress / HonoCustom

Examples

Ready-to-deploy example projects in the examples/ directory:

ExampleDescription
01-simple-agentMinimal hello-world agent with Durable Object memory
02-rag-agentFull tiered memory — episodic (D1) + semantic RAG (Vectorize)
03-research-workflowMulti-step research pipeline using Cloudflare Workflows

Each example includes a wrangler.toml, package.json, and README with setup instructions.

Workflows (Phase 3)

Honi wraps Cloudflare Workflows with a simple workflow() + step() API for durable, multi-step agent pipelines.

import { workflow, step } from 'honidev';

const IngestWorkflow = workflow({
  steps: [
    step({ name: 'fetch-data', retries: { limit: 3, backoff: 'exponential' } }, async (input, step) => {
      const res = await fetch(input.url);
      return res.json();
    }),
    step({ name: 'process', timeout: '60s' }, async (data, step) => {
      return { processed: true, items: data.length };
    }),
  ],
  onComplete: async (result, env) => {
    console.log('Pipeline complete:', result);
  },
  onError: async (error, env) => {
    console.error('Pipeline failed:', error.message);
  },
});

export { IngestWorkflow };

Add to wrangler.toml:

[[workflows]]
name = "ingest-workflow"
binding = "INGEST_WORKFLOW"
class_name = "IngestWorkflow"

CLI (Phase 4)

Honi includes a CLI for scaffolding and managing projects.

# Install globally
npm install -g honidev

# Create a new project
honi new my-sales-coach

# Start local dev server
honi dev

# Deploy to Cloudflare Workers
honi deploy

honi new generates a ready-to-run project with src/index.ts, wrangler.toml, tsconfig.json, and package.json.

Observability (Phase 5)

Honi emits structured events for every agent request, tool call, memory operation, and workflow step.

Configuration

const agent = createAgent({
  name: 'my-agent',
  model: 'claude-sonnet-4-5',
  observability: {
    logLevel: 'debug',
    onEvent: (event) => {
      // Send to your logging/analytics service
      console.log(event.type, event.durationMs);
    },
    aiGateway: {
      accountId: 'your-cf-account-id',
      gatewayId: 'your-gateway-id',
    },
  },
});

Event Types

EventEmitted When
agent.requestIncoming chat request
agent.responseResponse stream complete
tool.callTool execution starts
tool.resultTool execution finishes
memory.loadMemory loaded from storage
memory.saveMemory persisted
workflow.startWorkflow begins
workflow.stepWorkflow step executes
workflow.completeWorkflow finishes
workflow.errorWorkflow errors

AI Gateway

Set observability.aiGateway to route LLM calls through Cloudflare AI Gateway for logging, rate limiting, and caching at the edge.

API Reference

createAgent(config)

OptionTypeDefaultDescription
namestringAgent name
modelstringModel ID (claude-sonnet-4-5, gpt-4o)
systemstringSystem prompt
memoryMemoryConfig{}Memory configuration (see Phase 2)
toolsToolDefinition[][]Agent tools
bindingstring"AGENT"Durable Object binding name
maxStepsnumber10Max tool-calling loop iterations

Returns { fetch, DurableObject }.

tool(config)

OptionTypeDescription
namestringTool name (sent to LLM)
descriptionstringWhat the tool does
inputZodTypeZod schema for tool input
handler(input) => Promise<unknown>Tool implementation

License

MIT

Bundle Size

Honi is designed to fit comfortably within Cloudflare Workers' limits:

ComponentSize
Honi library (dist/)~30 KB
Full demo app (with AI SDK)691 KB uncompressed
Gzip compressed123 KB
CF Workers limit1 MB compressed

You're using ~12% of the limit with a full-featured agent including all AI SDK providers.

Optimization Tips

  • Only import the providers you need (@ai-sdk/anthropic OR @ai-sdk/openai, not both)
  • Use Workers AI (@cf/ models) to skip external provider SDKs entirely
  • Tree-shaking works — unused features don't add to bundle size

MCP Server

Honi agents can expose their tools as MCP endpoints, allowing connection from Claude Desktop, Cursor, and other MCP-compatible clients.

Endpoints

EndpointMethodDescription
/mcpPOSTJSON-RPC 2.0 MCP endpoint
/mcp/toolsGETList available tools (convenience)

Authentication

For remote connections (Cursor, custom clients, any non-local use) you should lock down /mcp with a Bearer token. Set mcp.secretEnvVar in your agent config:

const agent = createAgent({
  name: 'my-agent',
  model: 'claude-sonnet-4-5',
  tools: [searchDocs],
  mcp: { secretEnvVar: 'MCP_SECRET' },
})

Then set the secret via Wrangler:

wrangler secret put MCP_SECRET

Clients send Authorization: Bearer <secret> on every request. If secretEnvVar is not set, /mcp is unauthenticated — fine for local Claude Desktop (stdio transport), but don't expose it publicly without this.

Example: Connect from Claude Desktop

Add to your Claude Desktop MCP config:

{
  "mcpServers": {
    "my-honi-agent": {
      "url": "https://my-agent.workers.dev/mcp"
    }
  }
}

For authenticated remote connections:

{
  "mcpServers": {
    "my-honi-agent": {
      "url": "https://my-agent.workers.dev/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-here"
      }
    }
  }
}

Multi-Agent Orchestration

Honi supports agent-to-agent communication for building complex agentic workflows.

import { routeToAgent, callAgentTool, listAgentTools } from 'honidev';

// Send a message to another agent
const response = await routeToAgent(env, { binding: 'OTHER_AGENT' }, 'Hello!');

// Call a specific tool on another agent
const result = await callAgentTool(env, { binding: 'OTHER_AGENT' }, 'search', { query: 'test' });

// List available tools from another agent
const tools = await listAgentTools(env, { binding: 'OTHER_AGENT' });

wrangler.toml Setup

[[durable_objects.bindings]]
name = "MY_AGENT"
class_name = "MyAgentDO"

[[durable_objects.bindings]]
name = "OTHER_AGENT"
class_name = "OtherAgentDO"

FAQs

Package last updated on 08 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts