{"_id":"@arcanic-ai/cono-agent-sdk","_rev":"6-348f555eaf25d2bc104bd83fec6f4fee","name":"@arcanic-ai/cono-agent-sdk","dist-tags":{"latest":"0.1.5"},"versions":{"0.1.0":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.0","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","_id":"@arcanic-ai/cono-agent-sdk@0.1.0","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"homepage":"https://github.com/arcanic-ai/cono-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-sdk/issues"},"dist":{"shasum":"507ef351d70217313313488056646782bb5a4963","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.0.tgz","fileCount":42,"integrity":"sha512-Enrs9vqR6xjWXz23epIRgaBKJte5pYTvKfgvOic71VoU0/furGVD+Knvv5Y8pQJuM3AKKxpE25w4GfZLudoEtg==","signatures":[{"sig":"MEUCIGfJfJbaGGs45NT1PEPJYYX5NETKhPn8WVwfCes3ESlFAiEAjrdvSCFl10xeiq582fRRS8ppNS3ZspEzDEwR610Ip5U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":214713},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"repository":{"url":"git+https://github.com/arcanic-ai/cono-sdk.git","type":"git"},"_npmVersion":"11.8.0","description":"Agent SDK for building AI agents using Arcanic's OpenAI-compatible API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cono-agent-sdk_0.1.0_1773220692356_0.11424862517806877","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.1","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","_id":"@arcanic-ai/cono-agent-sdk@0.1.1","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"dist":{"shasum":"2f08d2a06c789f9cc23b2ed474a36c007fc612fc","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.1.tgz","fileCount":42,"integrity":"sha512-ip1EXTgt7ldwpkdYabPmhD8bRoHd7btHJefdldePoXlW+yejwSgGLIcKoDa8Y/KB6gsnAV4i8AJBNOrrRSOiEQ==","signatures":[{"sig":"MEQCIHwgbzoNlz/wG3iiIjQhYIzmzin5lHItUhY+fdxI2jGdAiAExPIlWyLXfNjwJNh7oA5Q25pLWEjtXns1CYHemsQdJA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":233907},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"repository":{"url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git","type":"git"},"_npmVersion":"11.8.0","description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cono-agent-sdk_0.1.1_1773227505625_0.21057014291757215","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.2","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","_id":"@arcanic-ai/cono-agent-sdk@0.1.2","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"dist":{"shasum":"6988561305aaef10798d74dc165d9e66d0329fbe","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.2.tgz","fileCount":42,"integrity":"sha512-6V6ziToVW5yjAr0DuifRIAqaVfgm6Sdbg91EnWl/C6/8g361IRoBCgcS2slTeOQkUJ/wVDl2sMDJjmHCavLNtA==","signatures":[{"sig":"MEUCIQDXZLsnqAJQnbVbcDrnFnQwV5qcecKjProAXqDcqE7WiwIgVDzPrTWmQ7tPGtEV5PY177PfECJne23rHrB60Ggf+LM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":233894},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"repository":{"url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git","type":"git"},"_npmVersion":"11.8.0","description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cono-agent-sdk_0.1.2_1773227672201_0.1784777944218927","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.3","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","_id":"@arcanic-ai/cono-agent-sdk@0.1.3","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"dist":{"shasum":"f23671076f9b30a1c807e0298996fb9c5d4bce7e","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.3.tgz","fileCount":42,"integrity":"sha512-LlMwhGlPOqjZ/77+bBPdTXSDqOPv/kBZ6h7vCTFvc/Yi6kn/8ZtSkGQ/WwepSsvKTDMURe0L/rR3AeFjVIYjIg==","signatures":[{"sig":"MEQCIAvD5otKmCGuj9NPAyv5o+9a6SGWW9BoS0rKfQZDtoQ3AiA+PQoEiUlJakuU6ckZ/JBELztKplQbnmtrf6SA3zE12g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":232440},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"repository":{"url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git","type":"git"},"_npmVersion":"11.8.0","description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cono-agent-sdk_0.1.3_1773228530883_0.014167745260054154","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.4","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","_id":"@arcanic-ai/cono-agent-sdk@0.1.4","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"dist":{"shasum":"8088b4725cb3226ff3fe456020b68d468b593d52","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.4.tgz","fileCount":42,"integrity":"sha512-Xr1XxAExXVxSLp09fqtmp0DA/zcXf34p2p7yEb6fNdgr8+seF3AA9EXrCde8y3iMJBUcZp1e8OAzr6gf6DIFDQ==","signatures":[{"sig":"MEUCIFodaZt9EvK665covx8nTLWItf1nIael1PpNeZSAJekpAiEA3f/E5EDnv7kbyJDYBuASv/OW7/LDG9ZbS2igPyw2jdY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":251251},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","scripts":{"dev":"tsc --watch","build":"tsc","clean":"rm -rf dist","prepublishOnly":"npm run build"},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"repository":{"url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git","type":"git"},"_npmVersion":"11.8.0","description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","directories":{},"_nodeVersion":"24.13.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.5.0","@types/node":"^25.4.0"},"_npmOperationalInternal":{"tmp":"tmp/cono-agent-sdk_0.1.4_1773303029039_0.3583813000421423","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@arcanic-ai/cono-agent-sdk","version":"0.1.5","description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc","dev":"tsc --watch","clean":"rm -rf dist","prepublishOnly":"npm run build"},"engines":{"node":">=18.0.0"},"keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"author":{"name":"Arcanic AI"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git"},"homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"publishConfig":{"access":"public"},"peerDependencies":{"e2b":"^2.0.0"},"peerDependenciesMeta":{"e2b":{"optional":true}},"devDependencies":{"@types/node":"^25.4.0","e2b":"^2.14.1","typescript":"^5.5.0"},"gitHead":"328b4eefe410bf9c9270a36c58f9703e91630970","_id":"@arcanic-ai/cono-agent-sdk@0.1.5","_nodeVersion":"24.13.1","_npmVersion":"11.8.0","dist":{"integrity":"sha512-rRaVLpBVXhsU4Yvh2f4B2Gwt6/CYKVStpz1Q1HL/D0OQAbrbbJdjcGtu5kAdDMgg+ZHn7e95BZAEnxjTqOISgQ==","shasum":"b7c96a2b980797ecddfcc623e2dfc8bc83909f99","tarball":"https://registry.npmjs.org/@arcanic-ai/cono-agent-sdk/-/cono-agent-sdk-0.1.5.tgz","fileCount":50,"unpackedSize":305966,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCBcQ0dqpxLDWJUxyniBTHPAeKj2u+PhUdTv0pbSACA1gIgSu1klxezyTH6outdQ4jbkc/0bhZPf+ZiAiXF+zkF67I="}]},"_npmUser":{"name":"tinychiu","email":"taanh42@gmail.com"},"directories":{},"maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cono-agent-sdk_0.1.5_1773908888572_0.696063056380019"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-11T09:18:12.253Z","modified":"2026-03-19T08:28:08.859Z","0.1.0":"2026-03-11T09:18:12.512Z","0.1.1":"2026-03-11T11:11:45.767Z","0.1.2":"2026-03-11T11:14:32.353Z","0.1.3":"2026-03-11T11:28:51.045Z","0.1.4":"2026-03-12T08:10:29.197Z","0.1.5":"2026-03-19T08:28:08.733Z"},"bugs":{"url":"https://github.com/arcanic-ai/cono-agent-sdk/issues"},"author":{"name":"Arcanic AI"},"license":"MIT","homepage":"https://github.com/arcanic-ai/cono-agent-sdk#readme","keywords":["ai","agent","sdk","arcanic","openai","automation","code-generation","tool-use","function-calling"],"repository":{"type":"git","url":"git+https://github.com/arcanic-ai/cono-agent-sdk.git"},"description":"Agent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can understand codebases, use tools, and execute complex workflows.","maintainers":[{"name":"tinychiu","email":"taanh42@gmail.com"}],"readme":"# Cono Agent SDK\n\nAgent SDK for building AI agents using Arcanic's Cono API. Programmatically build autonomous agents that can use tools, maintain conversations, stream responses, and execute complex workflows.\n\n## Install\n\n```sh\nnpm install @arcanic-ai/cono-agent-sdk\n```\n\n## Examples\n\nFor complete example applications, see the [cono-sdk-examples](https://git.arcanic.ai/theblackhacker/cono-sdk-examples) repository.\n\n## Quick Start\n\n### Simple Prompt\n\n```typescript\nimport { prompt } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst result = await prompt(\"What is 2 + 2?\", {\n  apiKey: \"your-api-key\",\n  model: \"cono-3\",\n});\n\nif (result.subtype === \"success\") {\n  console.log(result.result);\n}\n```\n\n### Streaming with Tools\n\n```typescript\nimport { query, tool } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst readFile = tool({\n  name: \"read_file\",\n  description: \"Read a file from disk\",\n  parameters: {\n    type: \"object\",\n    properties: {\n      path: { type: \"string\", description: \"File path to read\" },\n    },\n    required: [\"path\"],\n  },\n  handler: async (args) => {\n    const fs = await import(\"fs/promises\");\n    return await fs.readFile(args.path as string, \"utf-8\");\n  },\n});\n\nfor await (const message of query(\"Read package.json and summarize it\", {\n  apiKey: \"your-api-key\",\n  tools: [readFile],\n})) {\n  switch (message.type) {\n    case \"assistant\":\n      console.log(\"Assistant:\", message.message.content);\n      break;\n    case \"tool_use\":\n      console.log(`Using tool: ${message.toolName}`);\n      break;\n    case \"tool_result\":\n      console.log(`Tool result received`);\n      break;\n    case \"result\":\n      console.log(\"Done:\", message.subtype);\n      break;\n  }\n}\n```\n\n### Multi-turn Session\n\n```typescript\nimport { createSession, tool } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst session = createSession({\n  apiKey: \"your-api-key\",\n  model: \"cono-3\",\n  systemPrompt: \"You are a helpful coding assistant.\",\n});\n\n// First message\nconst result1 = await session.prompt(\"What is TypeScript?\");\nconsole.log(result1);\n\n// Follow-up (maintains context)\nconst result2 = await session.prompt(\"How does it compare to JavaScript?\");\nconsole.log(result2);\n\n// Check usage\nconsole.log(session.getUsage());\n```\n\n### Streaming Partial Messages\n\n```typescript\nimport { query } from \"@arcanic-ai/cono-agent-sdk\";\n\nfor await (const message of query(\"Write a poem about coding\", {\n  apiKey: \"your-api-key\",\n  includePartialMessages: true,\n})) {\n  if (message.type === \"partial_assistant\") {\n    process.stdout.write(\"\\r\" + message.content);\n  }\n}\n```\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `ARCANIC_API_KEY` | Arcanic API key (required) |\n| `ARCANIC_MODEL` | Default model name |\n| `E2B_API_KEY` | E2B API key (for E2B execution environment) |\n\n## Available Models\n\n| Model | Context Length | Description |\n|-------|---------------|-------------|\n| `cono-3` | 400,000 tokens | General-purpose model (default) |\n| `cono-3-nano` | 400,000 tokens | Lightweight, faster model |\n| `cono-3-code` | 1,000,000 tokens | Optimized for code tasks |\n\nAll models support: tool calling, function calling, vision, JSON mode, and JSON output.\n\n## API Reference\n\n### `query(prompt, options)`\n\nCore function that runs the agent loop. Returns an `AsyncGenerator<SDKMessage>`.\n\n### `prompt(text, options)`\n\nSimplified function that runs the agent loop and returns only the final result.\n\n### `tool(options)`\n\nHelper to define a tool with its schema and handler.\n\n### `toolDefinition(options)`\n\nCreate a tool definition without a handler (for use by external tool runners).\n\n```typescript\nimport { toolDefinition } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst def = toolDefinition({\n  name: \"my_tool\",\n  description: \"Does something useful\",\n  parameters: {\n    type: \"object\",\n    properties: { input: { type: \"string\" } },\n    required: [\"input\"],\n  },\n});\n```\n\n### `AbortError`\n\nError class thrown when an operation is aborted via `AbortController`.\n\n```typescript\nimport { query, AbortError } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst controller = new AbortController();\n\ntry {\n  for await (const msg of query(\"...\", { abortController: controller })) {\n    // ...\n    if (shouldCancel) controller.abort();\n  }\n} catch (err) {\n  if (err instanceof AbortError) {\n    console.log(\"Operation was cancelled\");\n  }\n}\n```\n\n### `createSession(options)`\n\nCreates a stateful `Session` for multi-turn conversations.\n\n### `Session`\n\n- `session.send(text)` — Send a message, returns `AsyncGenerator<SDKMessage>`\n- `session.prompt(text)` — Send and get final result\n- `session.getMessages()` — Get conversation history\n- `session.getUsage()` — Get total token usage\n- `session.getInfo()` — Get session metadata\n- `session.abort()` — Cancel current operation\n- `session.clear()` — Clear conversation history\n- `session.destroy()` — Destroy E2B sandbox (if using E2B environment)\n- `session.getSandbox()` — Get E2B sandbox instance (for advanced use)\n- `session.getSandboxId()` — Get sandbox ID for reconnecting later\n\n### `ArcanicClient`\n\nLow-level HTTP client for the Arcanic API. Supports both streaming and non-streaming requests.\n\n```typescript\nimport { ArcanicClient } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst client = new ArcanicClient({\n  apiKey: \"your-api-key\",\n});\n\nconst completion = await client.createChatCompletion({\n  model: \"cono-3\",\n  messages: [{ role: \"user\", content: \"Hello!\" }],\n});\n```\n\n#### Streaming with ArcanicClient\n\n```typescript\nimport { ArcanicClient } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst client = new ArcanicClient({ apiKey: \"your-api-key\" });\n\nconst stream = await client.createChatCompletion({\n  model: \"cono-3\",\n  messages: [{ role: \"user\", content: \"Write a haiku\" }],\n  stream: true,\n});\n\nfor await (const chunk of stream) {\n  const content = chunk.choices[0]?.delta?.content;\n  if (content) process.stdout.write(content);\n}\n```\n\n### `ArcanicAPIError`\n\nError class thrown when the API returns an error response.\n\n```typescript\nimport { ArcanicClient, ArcanicAPIError } from \"@arcanic-ai/cono-agent-sdk\";\n\ntry {\n  await client.createChatCompletion({ ... });\n} catch (err) {\n  if (err instanceof ArcanicAPIError) {\n    console.log(err.status);  // HTTP status code\n    console.log(err.body);    // Response body\n  }\n}\n```\n\n## SDKMessage Types\n\nThe `query()` function yields different message types:\n\n| Type | Description |\n|------|-------------|\n| `assistant` | Model's text response. Access via `message.message.content` |\n| `tool_use` | Model is calling a tool. Has `toolName`, `toolInput`, `toolCallId` |\n| `tool_result` | Result from a tool call. Has `toolCallId`, `result` |\n| `result` | Final result. Subtype is `success` or `error` |\n| `system` | System message |\n| `partial_assistant` | Streaming partial content (when `includePartialMessages: true`) |\n\n```typescript\nfor await (const msg of query(\"...\", options)) {\n  switch (msg.type) {\n    case \"assistant\":\n      console.log(\"Assistant:\", msg.message.content);\n      break;\n    case \"tool_use\":\n      console.log(`Calling ${msg.toolName} with`, msg.toolInput);\n      break;\n    case \"tool_result\":\n      console.log(\"Tool returned:\", msg.result);\n      break;\n    case \"result\":\n      if (msg.subtype === \"success\") {\n        console.log(\"Final:\", msg.result);\n        console.log(\"Usage:\", msg.usage);\n      } else {\n        console.log(\"Error:\", msg.error);\n      }\n      break;\n    case \"partial_assistant\":\n      process.stdout.write(msg.content);\n      break;\n  }\n}\n```\n\n## Hooks System\n\nHooks allow you to intercept and respond to events during the agent loop.\n\n### Hook Events\n\n| Event | Description |\n|-------|-------------|\n| `PreToolUse` | Before a tool is executed |\n| `PostToolUse` | After a tool completes |\n| `SessionStart` | When the session starts |\n| `SessionEnd` | When the session ends |\n| `Stop` | When the agent stops |\n\n### Using Hooks\n\n```typescript\nimport { query } from \"@arcanic-ai/cono-agent-sdk\";\n\nfor await (const msg of query(\"...\", {\n  apiKey: \"your-api-key\",\n  hooks: {\n    PreToolUse: [\n      {\n        matcher: \"Bash\",  // Only match tools containing \"Bash\"\n        hooks: [\n          async (input, { signal }) => {\n            console.log(`About to run: ${input.toolName}`);\n            // Return { abort: true } to cancel the operation\n            return { continue: true };\n          },\n        ],\n      },\n    ],\n    PostToolUse: [\n      {\n        hooks: [\n          async (input, { signal }) => {\n            console.log(`Tool ${input.toolName} returned: ${input.toolResult}`);\n            return { continue: true };\n          },\n        ],\n      },\n    ],\n  },\n})) {\n  // ...\n}\n```\n\n## Output Format (JSON Schema)\n\nForce the model to output structured JSON matching a schema:\n\n```typescript\nimport { query } from \"@arcanic-ai/cono-agent-sdk\";\n\nfor await (const msg of query(\"List 3 programming languages with their use cases\", {\n  apiKey: \"your-api-key\",\n  outputFormat: {\n    type: \"json_schema\",\n    schema: {\n      name: \"languages\",\n      strict: true,\n      schema: {\n        type: \"object\",\n        properties: {\n          languages: {\n            type: \"array\",\n            items: {\n              type: \"object\",\n              properties: {\n                name: { type: \"string\" },\n                useCase: { type: \"string\" },\n              },\n              required: [\"name\", \"useCase\"],\n            },\n          },\n        },\n        required: [\"languages\"],\n      },\n    },\n  },\n})) {\n  if (msg.type === \"result\" && msg.subtype === \"success\") {\n    const data = JSON.parse(msg.result);\n    console.log(data.languages);\n  }\n}\n```\n\n## Permission Modes\n\nControl how the agent handles tool permissions:\n\n| Mode | Description |\n|------|-------------|\n| `default` | Use `canUseTool` callback for permission checks |\n| `acceptEdits` | Auto-approve file edit operations |\n| `bypassPermissions` | Skip all permission checks (use with caution) |\n| `plan` | Planning mode - tools are not executed |\n| `dontAsk` | Don't prompt for permissions, deny if not pre-approved |\n\n```typescript\nimport { query, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\n// Bypass all permission checks (dangerous!)\nfor await (const msg of query(\"...\", {\n  apiKey: \"your-api-key\",\n  tools: builtinTools().tools,\n  permissionMode: \"bypassPermissions\",\n})) {\n  // ...\n}\n```\n\n## Built-in Tools\n\nThe SDK ships with 9 ready-to-use tools. `builtinTools()` returns `{ tools, sandboxManager? }` — destructure `tools` to get the tool array:\n\n```typescript\nimport { query, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst { tools } = builtinTools();\n\nfor await (const msg of query(\"Read package.json and list dependencies\", {\n  apiKey: \"your-api-key\",\n  tools,\n})) {\n  if (msg.type === \"assistant\") console.log(msg.message.content);\n}\n```\n\n### Tool Overview\n\n| Tool | Description |\n|------|-------------|\n| **Read** | Read a file's contents (supports offset/limit for large files) |\n| **Write** | Write content to a file (creates parent directories automatically) |\n| **Edit** | Replace an exact string in a file with new content |\n| **LS** | List the contents of a directory |\n| **Glob** | Find files matching a glob pattern |\n| **Grep** | Search for a text pattern in files using grep |\n| **Bash** | Execute a shell command in bash |\n| **WebFetch** | Fetch a URL and return the response |\n| **WebSearch** | Search the web via SearXNG (Google, Bing, Brave, DuckDuckGo, etc.) |\n\n### Selecting Tools\n\nYou can include or exclude specific tools:\n\n```typescript\nimport { builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\n// Only filesystem tools\nconst { tools: fsTools } = builtinTools({ include: [\"Read\", \"Write\", \"Edit\", \"LS\", \"Glob\", \"Grep\"] });\n\n// Everything except shell access\nconst { tools: safeTools } = builtinTools({ exclude: [\"Bash\"] });\n```\n\n### Tool Configuration\n\nPass `options` to customize limits, timeouts, and security:\n\n```typescript\nconst { tools } = builtinTools({\n  options: {\n    cwd: \"/home/user/project\",       // Working directory (default: process.cwd())\n    maxReadSize: 2 * 1024 * 1024,    // Max file read size in bytes (default: 1MB)\n    maxWriteSize: 2 * 1024 * 1024,   // Max file write size in bytes (default: 1MB)\n    shellTimeout: 60_000,            // Bash timeout in ms (default: 30000)\n    maxShellOutput: 200 * 1024,      // Max shell output in bytes (default: 100KB)\n    allowNetworkAccess: true,        // Enable WebFetch/WebSearch (default: true)\n    allowedUrlPatterns: [\"https://.*\\\\.example\\\\.com\"],  // Restrict fetch URLs (default: [])\n    maxFetchSize: 2 * 1024 * 1024,   // Max fetch response size (default: 1MB)\n  },\n});\n```\n\n### E2B Execution Environment\n\nBy default, built-in tools (Read, Write, Edit, LS, Glob, Grep, Bash) execute on the local machine. You can run them inside an [E2B](https://e2b.dev/) cloud sandbox instead — a secure, isolated VM in the cloud.\n\nInstall the optional `e2b` dependency:\n\n```sh\nnpm install e2b\n```\n\n#### E2B Cloud\n\n```typescript\nimport { builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst { tools } = builtinTools({\n  options: {\n    executionEnvironment: {\n      type: \"e2b\",\n      apiKey: \"e2b_***\",       // or set E2B_API_KEY env var\n      template: \"my-template\",  // optional: custom sandbox template\n      timeout: 600,             // optional: sandbox lifetime in seconds (default: 300)\n    },\n  },\n});\n```\n\n#### E2B Self-Hosted\n\nIf you're running [E2B infrastructure](https://github.com/e2b-dev/infra) on your own cloud:\n\n```typescript\nconst { tools } = builtinTools({\n  options: {\n    executionEnvironment: {\n      type: \"e2b-selfhost\",\n      domain: \"e2b.mycompany.com\",  // required: your self-hosted domain\n      apiKey: \"e2b_***\",            // optional\n    },\n  },\n});\n```\n\n#### Syncing Local Files into the Sandbox\n\nUpload local directories into the E2B sandbox when it's created:\n\n```typescript\nconst { tools } = builtinTools({\n  options: {\n    executionEnvironment: {\n      type: \"e2b\",\n      syncPaths: [\"./src\", \"./package.json\"],  // upload these into the sandbox\n    },\n  },\n});\n```\n\n#### Reconnecting to an Existing Sandbox\n\nReuse a running sandbox across sessions by passing its ID:\n\n```typescript\nconst { tools, sandboxManager } = builtinTools({\n  options: {\n    executionEnvironment: {\n      type: \"e2b\",\n      sandboxId: \"sbx_abc123\",  // reconnect instead of creating new\n    },\n  },\n});\n\n// After session, get the sandbox ID for later reuse\nconsole.log(sandboxManager?.getSandboxId());\n```\n\n#### E2B with Sessions\n\nSessions automatically manage sandbox lifecycle:\n\n```typescript\nimport { createSession, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst { tools } = builtinTools({\n  options: {\n    executionEnvironment: { type: \"e2b\" },\n  },\n});\n\nconst session = createSession({\n  apiKey: \"your-api-key\",\n  tools,\n  executionEnvironment: { type: \"e2b\" },\n});\n\nconst result = await session.prompt(\"Install express and create a hello world server\");\nconsole.log(result);\n\n// Get sandbox ID for reconnecting later\nconsole.log(\"Sandbox ID:\", session.getSandboxId());\n\n// Destroy sandbox when done (releases cloud resources)\nawait session.destroy();\n```\n\n#### What runs where?\n\n| Tool | E2B mode | Local mode |\n|------|----------|------------|\n| Read, Write, Edit | Sandbox VM | Local filesystem |\n| LS, Glob, Grep | Sandbox VM | Local filesystem |\n| Bash | Sandbox VM | Local shell |\n| WebFetch | **Always local** | Local |\n| WebSearch | **Always local** | Local |\n\nWebFetch and WebSearch always run locally because they make HTTP requests and don't benefit from sandbox isolation.\n\n#### ExecutionEnvironment Options\n\n| Option | Type | Required | Description |\n|--------|------|----------|-------------|\n| `type` | `\"local\" \\| \"e2b\" \\| \"e2b-selfhost\"` | Yes | Execution environment type |\n| `apiKey` | `string` | No | E2B API key (fallback: `E2B_API_KEY` env var) |\n| `domain` | `string` | Yes (selfhost) | Self-hosted E2B domain |\n| `template` | `string` | No | E2B sandbox template ID |\n| `timeout` | `number` | No | Sandbox lifetime in seconds (default: 300) |\n| `syncPaths` | `string[]` | No | Local paths to upload into sandbox |\n| `sandboxId` | `string` | No | Existing sandbox ID to reconnect to |\n\n### Read\n\nRead a file from the filesystem.\n\n```typescript\n// The agent will call this tool as:\n// Read({ path: \"src/index.ts\" })\n// Read({ path: \"large-file.log\", offset: 1000, limit: 500 })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `path` | `string` | Yes | File path to read (relative to working directory) |\n| `offset` | `number` | No | Byte offset to start reading from (default: 0) |\n| `limit` | `number` | No | Maximum number of bytes to read |\n\n### Write\n\nWrite content to a file. Creates parent directories if they don't exist.\n\n```typescript\n// Write({ path: \"src/hello.ts\", content: \"export const hello = 'world';\" })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `path` | `string` | Yes | File path to write |\n| `content` | `string` | Yes | Content to write to the file |\n\n### Edit\n\nEdit a file by replacing an exact string match with new content.\n\n```typescript\n// Edit({ path: \"src/config.ts\", old_text: \"port: 3000\", new_text: \"port: 8080\" })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `path` | `string` | Yes | File path to edit |\n| `old_text` | `string` | Yes | Exact text to find (must match exactly once) |\n| `new_text` | `string` | Yes | Text to replace old_text with |\n\n### LS\n\nList the contents of a directory, returning name and type for each entry.\n\n```typescript\n// LS({ path: \"src\" })\n// LS({})  — lists current directory\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `path` | `string` | No | Directory path (default: current directory) |\n\n### Glob\n\nSearch for files matching a pattern.\n\n```typescript\n// Glob({ pattern: \"*.ts\" })\n// Glob({ pattern: \"package.json\", maxDepth: 3 })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `pattern` | `string` | Yes | File name pattern (e.g. `*.ts`, `package.json`) |\n| `maxDepth` | `number` | No | Maximum directory depth to search (default: 10) |\n\n### Grep\n\nSearch for a text pattern in files using grep.\n\n```typescript\n// Grep({ pattern: \"TODO\", include: \"*.ts\" })\n// Grep({ pattern: \"import.*from\", path: \"src\", ignoreCase: true })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `pattern` | `string` | Yes | Text pattern or regex to search for |\n| `path` | `string` | No | Directory or file to search in (default: current directory) |\n| `include` | `string` | No | File pattern to include (e.g. `*.ts`) |\n| `ignoreCase` | `boolean` | No | Case-insensitive search (default: true) |\n| `maxResults` | `number` | No | Maximum number of results (default: 50) |\n\n### Bash\n\nExecute a shell command in bash.\n\n```typescript\n// Bash({ command: \"npm install express\" })\n// Bash({ command: \"git status\", timeout: 5000 })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `command` | `string` | Yes | Shell command to execute |\n| `timeout` | `number` | No | Timeout in milliseconds (default: 30000) |\n\nDangerous commands (e.g. `rm -rf /`, `mkfs`, `dd`) are automatically blocked.\n\n### WebFetch\n\nFetch a URL and return the response. Has built-in SSRF protection (blocks localhost, private IPs, internal domains).\n\n```typescript\n// WebFetch({ url: \"https://api.github.com/repos/user/repo\" })\n// WebFetch({ url: \"https://example.com\", method: \"POST\", headers: { \"Authorization\": \"Bearer ...\" } })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `url` | `string` | Yes | URL to fetch |\n| `method` | `string` | No | HTTP method (default: GET) |\n| `headers` | `object` | No | Request headers |\n\n### WebSearch\n\nSearch the web using SearXNG, aggregating results from Google, Bing, Brave, DuckDuckGo and many others. Calls `POST https://mcpo.arcanic.ai/search/search` under the hood.\n\n```typescript\n// WebSearch({ query: \"TypeScript 5.0 new features\" })\n```\n\n| Parameter | Type | Required | Description |\n|-----------|------|----------|-------------|\n| `query` | `string` | Yes | The search query |\n\n### Full Example: Coding Agent with All Tools\n\n```typescript\nimport { query, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst messages: string[] = [];\n\nfor await (const msg of query(\n  \"Find all TODO comments in the src/ directory, then search the web for best practices on handling TODOs in production code, and write a summary to TODO-REPORT.md\",\n  {\n    apiKey: process.env.ARCANIC_API_KEY,\n    model: \"cono-3\",\n    tools: builtinTools({ options: { cwd: \"/home/user/project\" } }).tools,\n    systemPrompt: \"You are a thorough code reviewer.\",\n  }\n)) {\n  if (msg.type === \"tool_use\") {\n    console.log(`🔧 ${msg.toolName}(${JSON.stringify(msg.input).slice(0, 80)}...)`);\n  }\n  if (msg.type === \"assistant\") {\n    messages.push(msg.message.content as string);\n  }\n}\n\nconsole.log(\"Final:\", messages.at(-1));\n```\n\n## User Input & Clarifying Questions\n\nWhile working on a task, the agent may need to ask the user clarifying questions (e.g. \"Which database should I use?\" or \"Do you want unit tests?\"). This is handled via the `canUseTool` callback — the agent calls a special `AskUserQuestion` tool, and your app presents the questions to the user and returns their answers.\n\n### How It Works\n\n1. The agent calls the `AskUserQuestion` tool with a `questions` array\n2. Your `canUseTool` callback receives the tool call\n3. Your app displays the questions and collects answers (terminal prompt, web form, mobile dialog, etc.)\n4. You return the answers via `{ behavior: \"allow\", updatedInput: { questions, answers } }`\n5. The agent continues with the user's input\n\n### Question Format\n\nEach question contains:\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `question` | `string` | The full question text |\n| `header` | `string` | Short label (max 12 chars), e.g. \"Auth method\", \"Library\" |\n| `options` | `array` | 2-4 choices, each with `label` and `description` |\n| `multiSelect` | `boolean` | If `true`, user can select multiple options |\n\n### Example: Terminal App\n\n```typescript\nimport { query, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\nimport * as readline from \"readline\";\n\nfunction askQuestion(prompt: string): Promise<string> {\n  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n  return new Promise((resolve) => rl.question(prompt, (ans) => { rl.close(); resolve(ans); }));\n}\n\nfor await (const msg of query(\"Help me set up a new web project\", {\n  apiKey: process.env.ARCANIC_API_KEY,\n  tools: builtinTools().tools,\n  canUseTool: async (toolName, input) => {\n    // Handle clarifying questions\n    if (toolName === \"AskUserQuestion\") {\n      const questions = input.questions as any[];\n      const answers: Record<string, string> = {};\n\n      for (const q of questions) {\n        console.log(`\\n${q.header}: ${q.question}`);\n        q.options.forEach((opt: any, i: number) => {\n          console.log(`  ${i + 1}. ${opt.label} — ${opt.description}`);\n        });\n        console.log(`  (Enter a number, or type your own answer)`);\n\n        const response = await askQuestion(\"Your choice: \");\n        const idx = parseInt(response, 10) - 1;\n        answers[q.question] = idx >= 0 && idx < q.options.length\n          ? q.options[idx].label\n          : response; // free-text input\n      }\n\n      return { behavior: \"allow\", updatedInput: { questions, answers } };\n    }\n\n    // Auto-approve other tools\n    return { behavior: \"allow\" };\n  },\n})) {\n  if (msg.type === \"assistant\") console.log(msg.message.content);\n}\n```\n\n### Response Format\n\nReturn an object with `questions` (pass through the original array) and `answers` (a map of question text → selected label):\n\n```typescript\n{\n  behavior: \"allow\",\n  updatedInput: {\n    questions: input.questions,   // pass through as-is\n    answers: {\n      \"Which framework should we use?\": \"Next.js\",\n      \"Which features do you want?\": \"Auth, Database\",  // comma-separated for multiSelect\n    }\n  }\n}\n```\n\n### Tool Approval\n\nThe same `canUseTool` callback also handles tool permission requests. When the agent wants to run a tool that isn't auto-approved, your callback can approve, deny, or modify the input:\n\n```typescript\ncanUseTool: async (toolName, input) => {\n  if (toolName === \"AskUserQuestion\") {\n    return handleClarifyingQuestions(input);\n  }\n\n  // Show what the agent wants to do\n  console.log(`Agent wants to use ${toolName}:`, input);\n  const approved = await askQuestion(\"Allow? (y/n): \");\n\n  if (approved === \"y\") {\n    return { behavior: \"allow\" };                             // approve as-is\n    // return { behavior: \"allow\", updatedInput: modified };  // approve with changes\n  }\n  return { behavior: \"deny\", message: \"User rejected\" };     // deny with reason\n}\n```\n\n## Skills System\n\nSkills are reusable prompt-based capabilities that can be invoked via slash-command syntax (`/skill-name`) or loaded directly into the agent context.\n\n### Using Built-in Skills\n\nThe SDK provides 5 built-in skills: `explain`, `refactor`, `test`, `review`, `debug`.\n\n```typescript\nimport { createSkillRegistry, query, builtinTools } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst skills = createSkillRegistry(); // Includes built-in skills by default\n\n// Resolve a skill from user input\nconst resolved = skills.resolve(\"/review src/auth.ts\");\nif (resolved) {\n  // resolved.expandedPrompt contains the full prompt\n  for await (const msg of query(resolved.expandedPrompt, {\n    apiKey: \"your-api-key\",\n    tools: builtinTools().tools,\n  })) {\n    if (msg.type === \"assistant\") console.log(msg.message.content);\n  }\n}\n```\n\n### Defining Custom Skills\n\n```typescript\nimport { defineSkill, createSkillRegistry } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst translateSkill = defineSkill({\n  name: \"translate\",\n  description: \"Translate text to another language\",\n  argumentHint: \"<text> --to <language>\",\n  prompt: `Please translate the following text:\\n\\n{{input}}\\n\\nProvide the translation and explain any nuances.`,\n  requiredTools: [], // No tools needed for this skill\n});\n\nconst documentSkill = defineSkill({\n  name: \"document\",\n  description: \"Generate documentation for code\",\n  argumentHint: \"<file path>\",\n  prompt: `Generate comprehensive documentation for:\\n\\n{{input}}\\n\\nInclude:\\n- Overview\\n- Function signatures\\n- Parameters\\n- Return values\\n- Usage examples`,\n  requiredTools: [\"Read\", \"Write\"],\n});\n\n// Create registry with custom skills\nconst skills = createSkillRegistry({\n  includeBuiltins: true,   // Include built-in skills (default: true)\n  skills: [translateSkill, documentSkill],\n});\n\n// List all available skills\nconsole.log(skills.list());\n// => [{ name: \"explain\", description: \"...\", argumentHint: \"...\" }, ...]\n```\n\n### Skills as System Prompt\n\nAdd the skills list to your system prompt so the model knows how to use them:\n\n```typescript\nconst systemPrompt = `You are a coding assistant.\n\n${skills.generateSkillsPrompt()}`;\n// Output:\n// Available skills (user can invoke with /command syntax):\n// - /explain <code or topic>: Explain a piece of code or concept in detail\n// - /refactor <file path or code>: Refactor code for better readability...\n// - /translate <text> --to <language>: Translate text to another language\n```\n\n### Skills as Tools\n\nConvert skills to AgentTools so the model can invoke them directly:\n\n```typescript\nimport { query, builtinTools, createSkillRegistry } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst skills = createSkillRegistry();\n\nfor await (const msg of query(\"Review the auth module and suggest improvements\", {\n  apiKey: \"your-api-key\",\n  tools: [\n    ...builtinTools().tools,\n    ...skills.asTools(),  // Adds skill_explain, skill_refactor, etc.\n  ],\n})) {\n  if (msg.type === \"assistant\") console.log(msg.message.content);\n}\n```\n\n### SkillRegistry API\n\n| Method | Description |\n|--------|-------------|\n| `register(skill)` | Register a single skill |\n| `registerAll(skills)` | Register multiple skills |\n| `get(name)` | Get skill by name |\n| `list()` | List all skills (metadata only) |\n| `resolve(input)` | Parse `/command args` and expand prompt |\n| `generateSkillsPrompt()` | Generate prompt section listing skills |\n| `asTools()` | Convert skills to AgentTools |\n| `loadSkills(names)` | Load specific skills into context |\n\n## Sub-agent System\n\nThe SDK supports spawning sub-agents to handle specialized tasks. The main agent can dispatch work to sub-agents with their own system prompts, tools, and configurations.\n\n### Built-in Agents\n\nThe SDK provides 3 pre-built agent definitions:\n\n| Agent | Description |\n|-------|-------------|\n| `EXPLORE_AGENT` | Fast read-only codebase exploration. Tools: Read, LS, Glob, Grep |\n| `CODE_REVIEW_AGENT` | Code review with detailed feedback. Tools: Read, LS, Glob, Grep |\n| `TEST_AGENT` | Test generation for code. Tools: Read, Write, LS, Glob, Grep, Bash |\n\n### Using the Agent Tool\n\n```typescript\nimport {\n  query,\n  builtinTools,\n  createAgentDispatchTool,\n  EXPLORE_AGENT,\n  CODE_REVIEW_AGENT,\n  TEST_AGENT,\n} from \"@arcanic-ai/cono-agent-sdk\";\n\nconst options = {\n  apiKey: \"your-api-key\",\n  tools: builtinTools().tools,\n};\n\n// Create the Agent tool with available sub-agents\nconst agentTool = createAgentDispatchTool(\n  {\n    Explore: EXPLORE_AGENT,\n    CodeReview: CODE_REVIEW_AGENT,\n    Test: TEST_AGENT,\n  },\n  options\n);\n\n// Add the Agent tool to the tools array\nfor await (const msg of query(\"Review the auth module for security issues\", {\n  ...options,\n  tools: [...options.tools, agentTool],\n})) {\n  if (msg.type === \"assistant\") console.log(msg.message.content);\n}\n// The model can now call: Agent({ agent: \"CodeReview\", task: \"Review src/auth.ts\" })\n```\n\n### Defining Custom Agents\n\n```typescript\nimport { createAgentDispatchTool } from \"@arcanic-ai/cono-agent-sdk\";\nimport type { AgentDefinition } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst securityAuditor: AgentDefinition = {\n  description: \"Security-focused code auditor. Looks for vulnerabilities and security issues.\",\n  prompt: `You are a security auditor. Analyze code for:\n- SQL injection, XSS, CSRF vulnerabilities\n- Authentication/authorization flaws\n- Sensitive data exposure\n- Insecure dependencies\nBe thorough and provide remediation suggestions.`,\n  tools: [\"Read\", \"Grep\", \"Glob\"],  // Restrict to read-only tools\n  maxTurns: 25,\n  // model: \"cono-3-code\",  // Optional: use a different model\n};\n\nconst documentationWriter: AgentDefinition = {\n  description: \"Generates documentation for code\",\n  prompt: \"You are a technical writer. Generate clear, comprehensive documentation.\",\n  tools: [\"Read\", \"Write\", \"LS\", \"Glob\"],\n  maxTurns: 30,\n};\n\nconst agentTool = createAgentDispatchTool(\n  {\n    Security: securityAuditor,\n    Docs: documentationWriter,\n  },\n  options\n);\n```\n\n### AgentDefinition Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `description` | `string` | Yes | When to use this agent (shown to main agent) |\n| `prompt` | `string` | Yes | System prompt for the sub-agent |\n| `tools` | `string[]` | No | Allowed tool names (inherits from parent if omitted) |\n| `disallowedTools` | `string[]` | No | Tool names to block |\n| `model` | `string` | No | Model to use (inherits from parent if omitted) |\n| `maxTurns` | `number` | No | Max turns before stopping (default: 50) |\n\n### Security: Depth Limiting\n\nSub-agents can spawn their own sub-agents, but depth is limited to prevent infinite recursion:\n\n```typescript\nconst options = {\n  apiKey: \"your-api-key\",\n  tools: builtinTools().tools,\n  maxAgentDepth: 2,  // Default: 3. Set to 0 to disable sub-agents entirely\n};\n```\n\n### Getting Agent Info\n\n```typescript\nimport { getAgentInfoList, EXPLORE_AGENT, CODE_REVIEW_AGENT } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst agents = {\n  Explore: EXPLORE_AGENT,\n  CodeReview: CODE_REVIEW_AGENT,\n};\n\nconst info = getAgentInfoList(agents);\n// => [\n//   { name: \"Explore\", description: \"Fast read-only codebase exploration...\", model: undefined },\n//   { name: \"CodeReview\", description: \"Performs code review...\", model: undefined },\n// ]\n```\n\n## MCP Integration\n\nThe SDK supports [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) for connecting to MCP servers and using their tools.\n\n### Transport Types\n\n| Type | Description |\n|------|-------------|\n| `stdio` | Spawn child process, communicate via stdin/stdout |\n| `http` | Connect to an HTTP streamable endpoint |\n| `sse` | Connect to a Server-Sent Events endpoint |\n| `sdk` | In-process MCP server (for custom tools) |\n\n### Connecting to MCP Servers\n\n```typescript\nimport { McpManager, query } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst mcp = new McpManager();\n\n// Connect to MCP servers\nconst statuses = await mcp.connectServers([\n  // stdio: command string\n  \"npx -y @anthropic/mcp-server-filesystem /home/user/project\",\n\n  // stdio: full config\n  {\n    \"filesystem\": {\n      type: \"stdio\",\n      command: \"npx\",\n      args: [\"-y\", \"@anthropic/mcp-server-filesystem\", \"/home/user/project\"],\n      env: { NODE_ENV: \"production\" },\n    },\n  },\n\n  // HTTP endpoint\n  {\n    \"weather\": {\n      type: \"http\",\n      url: \"https://mcp.example.com/weather\",\n      headers: { Authorization: \"Bearer ...\" },\n    },\n  },\n]);\n\n// Check connection status\nfor (const status of statuses) {\n  console.log(`${status.name}: ${status.status}`);\n  if (status.status === \"connected\") {\n    console.log(`  Tools: ${status.tools?.map(t => t.name).join(\", \")}`);\n  }\n}\n\n// Use MCP tools with the agent\nfor await (const msg of query(\"List all files in the project\", {\n  apiKey: \"your-api-key\",\n  tools: mcp.getTools(),  // MCP tools become AgentTools\n})) {\n  if (msg.type === \"assistant\") console.log(msg.message.content);\n}\n\n// Cleanup\nawait mcp.disconnectAll();\n```\n\n### In-Process MCP Server (SDK Type)\n\nCreate an MCP server directly in your code without spawning a process:\n\n```typescript\nimport { McpManager, createSdkMcpServer } from \"@arcanic-ai/cono-agent-sdk\";\n\nconst mcp = new McpManager();\n\nawait mcp.connectServers([\n  {\n    \"calculator\": createSdkMcpServer({\n      name: \"calculator\",\n      tools: [\n        {\n          name: \"add\",\n          description: \"Add two numbers\",\n          inputSchema: {\n            type: \"object\",\n            properties: {\n              a: { type: \"number\" },\n              b: { type: \"number\" },\n            },\n            required: [\"a\", \"b\"],\n          },\n          handler: async (args) => ({\n            content: [{ type: \"text\", text: String(args.a + args.b) }],\n          }),\n        },\n        {\n          name: \"multiply\",\n          description: \"Multiply two numbers\",\n          inputSchema: {\n            type: \"object\",\n            properties: {\n              a: { type: \"number\" },\n              b: { type: \"number\" },\n            },\n            required: [\"a\", \"b\"],\n          },\n          handler: async (args) => ({\n            content: [{ type: \"text\", text: String(args.a * args.b) }],\n          }),\n        },\n      ],\n    }),\n  },\n]);\n\n// Tools available: calculator__add, calculator__multiply\n```\n\n### Tool Namespacing\n\nBy default, MCP tools are prefixed with the server name: `serverName__toolName`.\n\n```typescript\n// With namespacing (default)\nconst tools = mcp.getTools();\n// => [\"filesystem__read_file\", \"filesystem__write_file\", \"weather__get_forecast\"]\n\n// Without namespacing\nconst tools = mcp.getTools({ namespaced: false });\n// => [\"read_file\", \"write_file\", \"get_forecast\"]\n```\n\n### McpManager API\n\n| Method | Description |\n|--------|-------------|\n| `connectServers(specs)` | Connect to multiple MCP servers |\n| `getStatuses()` | Get connection status of all servers |\n| `getTools(options?)` | Get all MCP tools as AgentTools |\n| `disconnect(name)` | Disconnect a specific server |\n| `disconnectAll()` | Disconnect all servers |\n\n### Security Notes\n\nThe SDK includes built-in security measures:\n\n- **Environment Filtering**: Sensitive environment variables (API keys, secrets, passwords) are automatically filtered when spawning stdio processes\n- **SSRF Protection**: URLs for HTTP/SSE connections are validated to block localhost, private IPs, and internal domains\n- **Command Validation**: Stdio commands are checked to prevent shell injection\n\n```typescript\n// These will be blocked:\n// - http://localhost:3000 (localhost)\n// - http://192.168.1.1 (private IP)\n// - http://metadata.google.internal (cloud metadata)\n\n// Environment variables like ARCANIC_API_KEY, AWS_SECRET_KEY, etc.\n// are NOT passed to MCP server processes\n```\n\n### Full Example: Agent with MCP + Skills + Built-in Tools\n\n```typescript\nimport {\n  query,\n  builtinTools,\n  McpManager,\n  createSkillRegistry,\n} from \"@arcanic-ai/cono-agent-sdk\";\n\nasync function main() {\n  // Setup MCP\n  const mcp = new McpManager();\n  await mcp.connectServers([\n    \"npx -y @anthropic/mcp-server-github\",\n  ]);\n\n  // Setup Skills\n  const skills = createSkillRegistry();\n\n  // Get user input\n  const userInput = \"/review the authentication flow\";\n  const resolved = skills.resolve(userInput);\n  const prompt = resolved?.expandedPrompt ?? userInput;\n\n  // Run agent with all tools\n  for await (const msg of query(prompt, {\n    apiKey: process.env.ARCANIC_API_KEY,\n    systemPrompt: `You are a senior developer.\\n\\n${skills.generateSkillsPrompt()}`,\n    tools: [\n      ...builtinTools().tools,\n      ...mcp.getTools(),\n      ...skills.asTools(),\n    ],\n  })) {\n    if (msg.type === \"tool_use\") {\n      console.log(`🔧 ${msg.toolName}`);\n    }\n    if (msg.type === \"assistant\") {\n      console.log(msg.message.content);\n    }\n  }\n\n  await mcp.disconnectAll();\n}\n\nmain();\n```\n\n## QueryOptions\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `apiKey` | `string` | API key (falls back to `ARCANIC_API_KEY` env var) |\n| `model` | `string` | Model name (falls back to `ARCANIC_MODEL` env var) |\n| `systemPrompt` | `string` | System prompt |\n| `maxTurns` | `number` | Max agent loop turns (default: 100) |\n| `maxTokens` | `number` | Max output tokens (default: 8192) |\n| `temperature` | `number` | Sampling temperature (0-2) |\n| `topP` | `number` | Top-p sampling parameter (0-1) |\n| `tools` | `AgentTool[]` | Tool definitions |\n| `allowedTools` | `string[]` | Tool names that are auto-allowed |\n| `disallowedTools` | `string[]` | Tool names that are blocked |\n| `canUseTool` | `CanUseTool` | Permission callback |\n| `permissionMode` | `PermissionMode` | Permission mode |\n| `outputFormat` | `OutputFormat` | Structured output format |\n| `includePartialMessages` | `boolean` | Enable streaming partial messages |\n| `hooks` | `Record<HookEvent, ...>` | Event hooks |\n| `agents` | `Record<string, AgentDefinition>` | Custom sub-agent definitions |\n| `maxAgentDepth` | `number` | Max sub-agent nesting depth (default: 3) |\n| `cwd` | `string` | Working directory for the session |\n| `headers` | `Record<string, string>` | Custom HTTP headers |\n| `timeout` | `number` | Request timeout (ms) |\n| `abortController` | `AbortController` | For cancelling the query |\n| `executionEnvironment` | `ExecutionEnvironment` | Execution environment for built-in tools (default: `{ type: 'local' }`) |\n\n## License\n\nMIT\n","readmeFilename":"README.md"}