Skip to content

AI toolkit: provider-agnostic text generation, structured output, tools/agents and embeddings #41

Description

@eaguad1337

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

  • Subsystem implemented under src/masonite/ai/ (contracts, manager, drivers, traits, agent/tools/conversation types, provider, facade, config).
  • make:agent command + stub registered.
  • Tests in 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.
  • Full pytest suite green.
  • Documentation page + nav entry.
  • Release-notes entry in the version that ships it.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:aiAI toolkit: providers, agents, embeddingsenhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions