Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

Adonis AI

TestsnpmTypeScriptLicense

An agent-oriented AI SDK for AdonisJS 7.

adonis-ai gives Adonis applications one typed API for AI SDK-compatible language models. Use OpenAI and Anthropic directly, reach every model available through Vercel AI Gateway, or register any official, community, self-hosted, registry-backed, or middleware-wrapped AI SDK language model. The first release focuses on the parts needed to build dependable text agents: streaming, structured output, application tools, observability, cancellation, and network-free tests.

The npm badge above is the source of truth for the current version. During 0.x, breaking changes ship only at minor-version boundaries with migration notes.

The 0.1 public API, provider, security, testing, troubleshooting, and upgrade guide defines the supported stable contract.

Compatibility

DependencySupported version
AdonisJS^7.0.0
Node.js>=24.0.0
Zod^4.0.0
Vercel AI SDKCore, AI Gateway, and compatible language models
OpenAIResponses API via @ai-sdk/openai
AnthropicMessages API via @ai-sdk/anthropic

What is included

  • Reusable BaseAgent classes and an agent({...}) factory
  • Vercel AI Gateway access to its full language-model catalog
  • A public shared adapter for any AI SDK-compatible language model
  • Built-in direct OpenAI Responses and Anthropic Messages drivers
  • Async-iterable streaming with SSE conversion
  • Zod 4 structured output with provider-native JSON Schema
  • Zod-validated application tools and a shared multi-step tool loop
  • Normalized responses, token usage, steps, request IDs, and errors
  • Abort and timeout propagation, including SSE disconnect cancellation
  • Adonis IoC singleton, typed events, configure hook, and Ace generators
  • Queued or dynamic fakes with prompt assertions and stray-call prevention
  • A real AdonisJS playground with functional and browser tests

The current Adonis agent surface covers text generation, streaming, structured output, application tools, provider-neutral image/document input, application-owned conversations, provider options, retries, timeouts, cancellation, and middleware-wrapped language models. Provider-executed tools, embeddings, image/video generation, speech, transcription, reranking, realtime, provider-stored conversations, queues, approvals, MCP, and vector stores remain deferred.

Repository layout

packages/adonis-ai Publishable SDK package
apps/playground AdonisJS 7 consumer app and package lab

Quick start

npm install adonis-ai zod
node ace configure adonis-ai

Set at least one provider and model in .env.

AI_DEFAULT_PROVIDER=openaiOPENAI_API_KEY=OPENAI_MODEL=ANTHROPIC_API_KEY=ANTHROPIC_MODEL=AI_GATEWAY_API_KEY=AI_GATEWAY_MODEL=openai/gpt-5

Create an agent.

node ace make:ai-agent Support
import{BaseAgent}from"adonis-ai";exportdefaultclassSupportAgentextendsBaseAgent{instructions(){return"Answer product questions clearly and concisely.";}}

Use direct construction for dependency-free agents, or ai.make when the Adonis container should construct the class.

importSupportAgentfrom"#ai/agents/support_agent";importaifrom"adonis-ai/services/main";constagent=awaitai.make(SupportAgent);constresponse=awaitagent.prompt("How do I reset my password?");console.log(response.text);console.log(response.usage);console.log(response.steps);

Streaming

Every stream is an async iterable and can also be sent directly from an Adonis controller.

conststream=agent.stream("Explain server-sent events");forawait(consteventofstream){if(event.type==="text.delta"){process.stdout.write(event.delta);}}constfinal=awaitstream.finalResponse();
asyncstream({ response }: HttpContext){conststream=agent.stream('Explain server-sent events')response.header('Content-Type','text/event-stream')returnresponse.stream(stream.toSseReadable())}

Normalized events are:

  • run.started
  • text.delta
  • tool.started
  • tool.completed
  • step.completed
  • run.completed
  • run.failed

Destroying the readable SSE stream aborts the upstream provider request.

Structured output

import{BaseAgent}from"adonis-ai";import{z}from"zod";constoutput=z.object({summary: z.string(),risks: z.array(z.string()),});classReviewAgentextendsBaseAgent<typeofoutput>{readonlyoutputSchema=output;instructions(){return"Review the input and identify its risks.";}}constresponse=awaitnewReviewAgent().prompt("Review this proposal");response.data.summary;// stringresponse.data.risks;// string[]

The adapter asks the provider to enforce JSON Schema, then the shared engine parses and validates the completed value with Zod. During structured streaming, text deltas remain partial strings and typed data is exposed only on the final response.

Application tools

import{defineTool}from"adonis-ai";import{z}from"zod";constweather=defineTool({name: "weather",description: "Get the weather for a city",input: z.object({city: z.string()}),asyncexecute({ city },{ signal }){returngetWeather(city,{ signal });},});

Return tools from an agent’s tools() method. Multiple tool requests are executed sequentially in provider order. The default maximum is eight model steps. Input and handler errors are sent back to the model as safe tool results; pass { toolErrorMode: 'throw' } to stop immediately.

Conversations

Register an application-owned store and pass a conversation identifier. The SDK loads history before the run and atomically appends the successful user, assistant, and tool messages before emitting completion.

importtype{ConversationStore}from"adonis-ai";constconversations: ConversationStore={load: (id)=>database.loadMessages(id),append: (id,turn)=>database.appendTurn(id,turn.runId,turn.messages),};ai.useConversationStore(conversations);awaitagent.prompt("Continue our discussion",{conversation: {id: "conversation_123"},});

Nothing is persisted by default. Failed, cancelled, and maximum-step runs append nothing; load or append failures reject with ConversationPersistenceError.

Image and document input

String prompts remain supported. For multimodal input, pass text and file parts using bytes, base64, or an absolute HTTP(S) URL.

awaitagent.prompt([{type: "text",text: "Summarize this report"},{type: "file",mediaType: "application/pdf",filename: "report.pdf",source: {type: "bytes",data: uploadedBytes},},]);

Direct OpenAI and Anthropic support JPEG, PNG, GIF, WebP, and PDF; Anthropic also supports text/plain. Gateway and custom adapters must declare attachment capabilities explicitly. Applications own file-size limits, URL policy, durable storage, and upload authorization. See the conversations and files guide.

Testing

importaifrom"adonis-ai/services/main";constfake=ai.fake(["First answer",{data: {summary: "Typed fake",risks: []}},{text: "Streamed",chunks: ["Stream","ed"]},]).preventStrayRequests();awaitagent.prompt("Question");fake.assertPrompted("Question");

Dynamic fakes receive both the recorded prompt and normalized provider request, so tests can model tool loops without network access.

Local development

Requires Node.js 24 and npm 11.

npm install
npm run check
npm run dev --workspace playground

The playground resolves adonis-ai directly from the local workspace and acts as an executable feature catalog. It covers direct providers and Gateway, ordinary and structured generation, streaming, local tools, application-owned conversations, every attachment source, one-off message history, run limits, provider options, raw response opt-in, normalized events, and cancellation. Its functional and browser suites use package fakes, so the examples stay deterministic.

To verify the exact artifact that npm consumers receive, run the isolated package-consumer check:

npm run test:package-consumer

This packs the SDK, installs the tarball into a temporary standalone copy of the playground, and runs its typecheck, tests, and production build.

Maintainers can follow the release qualification and publication checklist to verify live providers, npm dist-tags, provenance, and the published package.

The default suite never calls a real AI API. Live acceptance is opt-in and cost-bounded:

AI_LIVE_PROVIDER=openai npm run test:live:openai --workspace adonis-ai
AI_LIVE_PROVIDER=anthropic npm run test:live:anthropic --workspace adonis-ai
AI_LIVE_PROVIDER=gateway npm run test:live:gateway --workspace adonis-ai

Provider extensions

The built-in gateway driver uses creator/model IDs and reaches every language model available in Vercel AI Gateway with one API key:

exportdefaultdefineConfig({default: "gateway",providers: {gateway: {driver: "gateway",apiKey: env.get("AI_GATEWAY_API_KEY"),model: "anthropic/claude-sonnet-4",},},});

Gateway routing, fallback, attribution, and provider-specific settings pass through providerOptions:

awaitagent.prompt("Explain the tradeoff",{providerOptions: {gateway: {order: ["vertex","anthropic"],models: ["openai/gpt-5-mini"],tags: ["support"],},anthropic: {thinking: {type: "enabled",budgetTokens: 4_000},},},});

To use a provider package directly, install only that package and register its language model with the public adapter:

import{google}from"@ai-sdk/google";import{AiSdkProvider}from"adonis-ai/providers/ai-sdk";ai.extend("google",(_config,context)=>{returnnewAiSdkProvider({name: context.name,providerOptionsKey: "google",model: (modelId)=>google(modelId),});});

This same entrypoint accepts AI SDK provider registries, community and self-hosted providers, custom providers, and models wrapped with AI SDK middleware. For a non-AI-SDK integration, implement ProviderAdapter directly:

ai.extend("community-driver",(config,context)=>{returnnewCommunityProvider(config,context.name);});

The Vercel AI SDK provider layer translates model requests, responses, errors, usage, and streaming events. Agent composition and the multi-step application tool loop remain in Adonis AI, preserving the existing public API and extension contract. Individual providers and models still differ in capability; Adonis AI forwards supported features and normalizes their results rather than emulating capabilities a model does not have.

Security defaults

  • OpenAI response storage defaults to false
  • Prompts are excluded from emitted events unless explicitly enabled
  • Raw provider payloads are opt-in and typed as unknown
  • Default timeout is 60 seconds with two SDK-level retries
  • API keys are never included in normalized events or errors

Support

Acknowledgements

The developer experience follows AdonisJS and TypeScript conventions and uses Vercel AI SDK Core. OpenAI uses its Responses API; Anthropic uses its Messages API.

MIT licensed.

About

A typed, agent-oriented AI SDK for AdonisJS 7 with OpenAI and Anthropic support.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages