Problem
Building AI features in a Masonite app today means wiring an AI provider's HTTP API by hand in every project — managing keys, request/response shapes, tool-call loops, and retries inline. There is no first-party, provider-agnostic way to generate text, get structured output, give a model tools, hold a conversation, or produce embeddings.
Proposal
Add an AI toolkit to the core (src/masonite/ai/) that exposes one fluent, swappable-provider API, built the same way as Mail/Cache/Queue: a manager that resolves a driver from config, a AI facade, and a set of interfaces (contracts) and traits (mixins) so apps extend it without forking.
from masonite.facades import AI
# text generation
reply = AI.generate("Summarise this changelog: ...").text()
# structured output (schema-constrained)
data = AI.structured(SCHEMA, "Extract the name and email from: ...")
# a conversation with history
chat = AI.conversation().system("You are concise.")
chat.send("Who wrote Don Quixote?")
chat.send("And in what century?")
# an agent with tools
class SupportAgent(Agent):
def instructions(self): return "Help with orders."
def tools(self): return [LookupOrder()]
AI.agent(SupportAgent).run("Where is order 1234?")
Capabilities (first cut)
- Text generation — prompt/messages → response (text, token usage, raw payload).
- Structured output — responses constrained to a JSON schema and validated.
- Tool calling & agents — define tools (interface + decorator); an
Agent base class drives the generate → call tool → feed result loop.
- Conversations — an ordered message history for multi-turn exchanges.
- Embeddings — a contract for turning text into vectors (fulfilled by an embeddings-capable provider).
- Provider drivers — selected by config, starting with an Anthropic/Claude driver, plus a fake driver for tests (no network/keys).
Architecture
- Contracts (interfaces) in
ai/contracts/: a base AIDriver, plus capability mixins (SupportsStructuredOutput, SupportsTools, SupportsEmbeddings) a driver opts into. The manager raises a clear error when a provider is asked for a capability it doesn't implement.
- Traits (mixins) for app classes/models:
InteractsWithAI (prompt helper on any class) and Embeddable (generate/store an embedding for a model attribute).
- Manager + driver + config + facade, mirroring
src/masonite/mail/Mail.py, providers/MailProvider.py, facades/Mail.py, and a config/ai.py. Provider drivers call the HTTP API through the built-in Http client (no heavy SDK dependency), exactly like the existing Mailgun/Slack drivers use requests.
- Scaffolding — a
make:agent craft command + stub.
Definition of Done
Out of scope (follow-ups)
Streaming responses, image generation, audio (speech-to-text / text-to-speech), and additional provider drivers (OpenAI, Gemini, and a dedicated embeddings provider) are deliberately deferred to follow-up issues so this first cut establishes the architecture.
Problem
Building AI features in a Masonite app today means wiring an AI provider's HTTP API by hand in every project — managing keys, request/response shapes, tool-call loops, and retries inline. There is no first-party, provider-agnostic way to generate text, get structured output, give a model tools, hold a conversation, or produce embeddings.
Proposal
Add an AI toolkit to the core (
src/masonite/ai/) that exposes one fluent, swappable-provider API, built the same way as Mail/Cache/Queue: a manager that resolves a driver from config, aAIfacade, and a set of interfaces (contracts) and traits (mixins) so apps extend it without forking.Capabilities (first cut)
Agentbase class drives the generate → call tool → feed result loop.Architecture
ai/contracts/: a baseAIDriver, plus capability mixins (SupportsStructuredOutput,SupportsTools,SupportsEmbeddings) a driver opts into. The manager raises a clear error when a provider is asked for a capability it doesn't implement.InteractsWithAI(prompt helper on any class) andEmbeddable(generate/store an embedding for a model attribute).src/masonite/mail/Mail.py,providers/MailProvider.py,facades/Mail.py, and aconfig/ai.py. Provider drivers call the HTTP API through the built-inHttpclient (no heavy SDK dependency), exactly like the existing Mailgun/Slack drivers userequests.make:agentcraft command + stub.Definition of Done
src/masonite/ai/(contracts, manager, drivers, traits, agent/tools/conversation types, provider, facade, config).make:agentcommand + stub registered.tests/features/ai/using the fake driver (zero network/keys), plus the real driver's request/response mapping asserted via the HTTP client's fake.pytestsuite green.Out of scope (follow-ups)
Streaming responses, image generation, audio (speech-to-text / text-to-speech), and additional provider drivers (OpenAI, Gemini, and a dedicated embeddings provider) are deliberately deferred to follow-up issues so this first cut establishes the architecture.