stukennedy/honi/claude-skill

Claude Code and agent skill by stukennedy/honi

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Build AI agents with Honi (honidev) on Cloudflare Workers. Use when creating agents with tools, persistent memory, MCP servers, or multi-agent pipelines. Covers createAgent API, tool() helper, all memory tiers (working/episodic/semantic/graph), multi-agent routing, MCP auth, and all supported model providers.

Install

npx vskill@latest install stukennedy/honi/claude-skill

SKILL.md

Honi — AI Agents on Cloudflare Workers

honidev is a TypeScript framework for building persistent AI agents on Cloudflare Workers using Durable Objects. Zero cold starts. Global edge deployment. Layered memory that survives across sessions.

Installation

bash
npm install honidev
# or
bun add honidev

Minimal Agent

typescript
// src/index.ts
import { createAgent, tool } from 'honidev'
import { z } from 'zod'
export const { Agent, handler } = createAgent({
name: 'my-agent',
model: 'claude-sonnet-4-5',
system: 'You are a helpful assistant.',
tools: [
tool('get_weather', 'Get weather for a location', {
location: z.string()
}, async ({ location }) => {
return { temp: 22, condition: 'sunny', location }
})
]
})
export default handler
export class MyAgent extends Agent {}
toml
# wrangler.toml
name = "my-agent"
main = "src/index.ts"
compatibility_date = "2025-01-01"
compatibility_flags = ["nodejs_compat"]
[[durable_objects.bindings]]
name = "AGENT"
class_name = "MyAgent"
[[migrations]]
tag = "v1"
new_classes = ["MyAgent"]

createAgent Config

typescript
createAgent({
name: string, // Worker name
model: string, // Model ID (see providers below)
system?: string, // System prompt
tools?: ToolDefinition[], // Array of tool() calls
binding?: string, // DO binding name (default: "AGENT")
maxSteps?: number, // Tool loop limit (default: 10)
memory?: MemoryConfig, // Memory tier config (see Memory section)
mcp?: McpConfig, // MCP server config (see MCP section)
aiGateway?: AiGatewayConfig, // Route LLM calls through CF AI Gateway (see AI Gateway section)
observability?: ObservabilityConfig,
})

tool() Helper

typescript
import { tool } from 'honidev'
import { z } from 'zod'
const myTool = tool(
'tool_name',
'Description of what the tool does',
{
param1: z.string().describe('First param'),
param2: z.number().optional(),
},
async ({ param1, param2 }, ctx) => {
// ctx.env → raw Worker env (access bindings, secrets)
// ctx.graph → GraphMemory instance (if graph memory enabled)
return { result: 'value' }
}
)

The handler receives (params, ctx?). The ctx argument is optional — tools without context still work fine.

HTTP API

Every agent exposes:

EndpointMethodDescription
/chatPOSTSend a message, get a response
/historyGETRetrieve conversation history
/memoryGETInspect current memory context
/resetPOSTClear working memory
/mcpPOSTMCP JSON-RPC endpoint

Thread isolation via header or query param:

bash
curl -X POST https://my-agent.workers.dev/chat \
-H "x-thread-id: user-123" \
-H "Content-Type: application/json" \
-d '{"message": "Hello"}'

Streaming

bash
curl -X POST https://my-agent.workers.dev/chat \
-H "Accept: text/event-stream" \
-d '{"message": "Tell me a story"}'

Returns Server-Sent Events. The client receives data: {"type":"text","text":"..."} chunks.

Memory — Four Tiers

Honi has four memory tiers. Enable only what you need.

typescript
memory: {
working: true, // Tier 1: Durable Object KV (always on)
episodic: { // Tier 2: D1 — conversation history
enabled: true,
dbBinding: 'DB', // D1 binding name in wrangler.toml
maxMessages: 50,
},
semantic: { // Tier 3: Vectorize — semantic search
enabled: true,
indexBinding: 'VECTORIZE',
aiBinding: 'AI', // Workers AI for embeddings
topK: 5,
},
graph: { // Tier 4: edgraph — knowledge graph
enabled: true,
binding: 'EDGRAPH', // Service binding OR
urlEnvVar: 'EDGRAPH_URL', // HTTP URL env var
apiKeyEnvVar: 'EDGRAPH_API_KEY',
graphId: 'my-graph',
contextDepth: 1, // BFS hops
maxContextEntities: 5,
}
}

wrangler.toml for full memory stack:

toml
[[durable_objects.bindings]]
name = "AGENT"
class_name = "MyAgent"
[[migrations]]
tag = "v1"
new_classes = ["MyAgent"]
[[d1_databases]]
binding = "DB"
database_name = "my-agent-db"
database_id = "<YOUR_D1_ID>"
[[vectorize]]
binding = "VECTORIZE"
index_name = "my-agent-index"
[ai]
binding = "AI"
[[services]]
binding = "EDGRAPH"
service = "edgraph"

Graph memory in tools:

typescript
tool('remember_person', 'Store a person in the knowledge graph', {
name: z.string(),
role: z.string(),
}, async ({ name, role }, ctx) => {
await ctx.graph.addNode({ id: name, label: name, type: 'Person', properties: { role } })
return { stored: true }
})

Multi-Agent Orchestration

Route requests to specialised agents at the Worker level:

typescript
// src/index.ts
import { createAgent } from 'honidev'
export const { Agent: SupportAgent, handler: supportHandler } = createAgent({
name: 'support',
model: 'claude-sonnet-4-5',
system: 'You handle customer support queries.',
binding: 'SUPPORT_DO',
tools: [searchKnowledgeBase],
})
export const { Agent: AnalystAgent, handler: analystHandler } = createAgent({
name: 'analyst',
model: 'claude-sonnet-4-5',
system: 'You analyse data and produce reports.',
binding: 'ANALYST_DO',
tools: [runQuery, generateChart],
})
export default {
async fetch(request: Request, env: Env) {
const url = new URL(request.url)
if (url.pathname.startsWith('/support')) return supportHandler.fetch(request, env)
if (url.pathname.startsWith('/analyst')) return analystHandler.fetch(request, env)
return new Response('Not found', { status: 404 })
}
}
export class SupportAgent extends SupportAgent {}
export class AnalystAgent extends AnalystAgent {}
toml
[[durable_objects.bindings]]
name = "SUPPORT_DO"
class_name = "SupportAgent"
[[durable_objects.bindings]]
name = "ANALYST_DO"
class_name = "AnalystAgent"
[[migrations]]
tag = "v1"
new_classes = ["SupportAgent", "AnalystAgent"]

MCP Server

Every agent exposes /mcp as an MCP JSON-RPC endpoint. Tools are automatically registered.

Connect from Claude Desktop:

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

Add authentication for remote connections (recommended):

typescript
createAgent({
// ...
mcp: { secretEnvVar: 'MCP_SECRET' }
})
bash
wrangler secret put MCP_SECRET

Claude Desktop with auth:

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

Supported Models

PrefixProviderExample
claude-*Anthropicclaude-sonnet-4-5
gpt-*, o1, o3OpenAIgpt-4o
gemini-*Googlegemini-2.5-flash-preview
groq/*Groqgroq/llama-3.3-70b-versatile
deepseek-*DeepSeekdeepseek-chat
mistral-*Mistralmistral-large-latest
grok-*xAIgrok-2-latest
sonar*Perplexitysonar-pro
together/*Together AItogether/meta-llama/Llama-3-70b
command-*Coherecommand-r-plus
@cf/*Workers AI@cf/meta/llama-3.1-8b-instruct

Workers AI models require an [ai] binding in wrangler.toml — no API key needed. Other providers use their respective API key set via wrangler secret, OR no key at all when routed through AI Gateway with stored keys / Unified Billing (see AI Gateway section).

Environment variable names:

  • Anthropic: ANTHROPIC_API_KEY
  • OpenAI: OPENAI_API_KEY
  • Google: GOOGLE_AI_API_KEY
  • Groq: GROQ_API_KEY
  • DeepSeek: DEEPSEEK_API_KEY
  • Mistral: MISTRAL_API_KEY
  • xAI: XAI_API_KEY
  • Perplexity: PERPLEXITY_API_KEY
  • Together: TOGETHER_API_KEY
  • Cohere: COHERE_API_KEY

AI Gateway

Route all LLM calls through Cloudflare AI Gateway. With BYOK keys stored in the gateway (or Unified Billing), the Worker needs no provider API keys:

typescript
createAgent({
// ...
aiGateway: {
gatewayId: 'my-gateway', // Gateway ID (slug) from the CF dashboard
accountId: 'cf-account-id', // Only needed without an [ai] binding
tokenEnvVar: 'CF_AIG_TOKEN', // Gateway auth token env var (default)
}
})

With an [ai] binding in wrangler.toml, only gatewayId is required — auth happens through the binding, fully keyless. Gateway routing covers Anthropic, OpenAI, Google, Groq, DeepSeek, Mistral, xAI, Perplexity, and Azure OpenAI. @cf/* models route through the gateway natively.

Observability

typescript
createAgent({
// ...
observability: {
logLevel: 'debug', // none | error | warn | info | debug
onEvent: (event) => console.log(event), // Structured event callback
}
})

Common Patterns

Tool that calls an external API
typescript
tool('search_docs', 'Search documentation', {
query: z.string(),
}, async ({ query }, ctx) => {
const apiKey = (ctx.env as any).DOCS_API_KEY
const res = await fetch(`https://api.example.com/search?q=${query}`, {
headers: { Authorization: `Bearer ${apiKey}` }
})
return res.json()
})
Tool that writes to D1
typescript
tool('save_note', 'Save a note to the database', {
title: z.string(),
content: z.string(),
}, async ({ title, content }, ctx) => {
const db = (ctx.env as any).DB as D1Database
await db.prepare('INSERT INTO notes (title, content) VALUES (?, ?)')
.bind(title, content).run()
return { saved: true }
})
Tool that writes to graph memory
typescript
tool('link_entities', 'Create a relationship between two entities', {
fromId: z.string(),
toId: z.string(),
relation: z.string(),
}, async ({ fromId, toId, relation }, ctx) => {
await ctx.graph.addEdge({ source: fromId, target: toId, label: relation })
return { linked: true }
})
Conditional memory based on content

The memory stack is write-through by default. To promote selectively, skip memory config and write to tiers manually in a tool or post-processing step. An evaluator / significance filter is on the roadmap.

Project Layout

src/
index.ts # createAgent + export DO class + default handler
agents/
support.ts # Specialist agent definitions
analyst.ts
tools/
search.ts # Tool definitions
database.ts
wrangler.toml
package.json

Quick Reference

TaskCode
Create agentcreateAgent({ name, model, system, tools })
Define tooltool(name, desc, schema, handler)
Access env in tool(params, ctx) => ctx.env.MY_BINDING
Access graph in tool(params, ctx) => ctx.graph.addNode(...)
Thread isolationx-thread-id header or ?threadId= query param
View historyGET /history?threadId=xyz
Reset sessionPOST /reset
Enable episodicmemory: { episodic: { enabled: true, dbBinding: 'DB' } }
Enable semanticmemory: { semantic: { enabled: true, indexBinding: 'VECTORIZE', aiBinding: 'AI' } }
Enable graphmemory: { graph: { enabled: true, binding: 'EDGRAPH', graphId: 'x' } }
MCP authmcp: { secretEnvVar: 'MCP_SECRET' }
Stream responseAccept: text/event-stream on POST /chat

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
41
Repository forks
1
Repository npm downloads, 7 days
25
7-day trend score
33

Stars and forks are for the whole GitHub repository, not this skill alone. Downloads are for the repository's npm package. Refreshed 27 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/stukennedy/honi/claude-skill/badge)](https://verified-skill.com/skills/stukennedy/honi/claude-skill)

Something wrong with this skill or its page? Tell us.