Skip to content

Provider support

Minion reaches models through LiteLLM, so switching provider is a model string:

minions.Minion(model="openai/gpt-4o", tools=[...])
minions.Minion(model="anthropic/claude-opus-4", tools=[...])
minions.Minion(model="gemini/gemini-2.5-pro", tools=[...])

API keys come from the standard environment variables (OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, GROQ_API_KEY, …) or from init(api_key=...).

Reaching a provider is not the same as working with it. Read the tiers below before committing to a model.

The one hard requirement: native structured output

Section titled “The one hard requirement: native structured output”

Every turn, Minion asks the model for a strict JSON object — a thought plus the tools to call — by passing a schema as response_format:

{"next_thought": "...", "next_tools": [{"tool_name": "...", "args": [...]}]}

Loose “JSON mode” is not enough. Without schema enforcement the model typically flattens the envelope — emitting a single bare tool call instead of the {next_thought, next_tools[]} wrapper — and the run dies on turn 1.

Check any model before committing to it:

import litellm
litellm.supports_response_schema(model="groq/openai/gpt-oss-120b") # True
litellm.supports_response_schema(model="groq/llama-3.3-70b-versatile") # False

OpenAI, Anthropic, Gemini. What Minion is developed against and what gets tested before a release. A bug here is a release blocker.

ProviderExample model
OpenAIopenai/gpt-4o
Anthropicanthropic/claude-opus-4
Geminigemini/gemini-2.5-pro

Any other LiteLLM-reachable provider whose model supports native JSON-schema output. Not part of the release test pass. Expect them to work; please report it if they don’t.

ModelNotes
groq/openai/gpt-oss-120bVerified end-to-end: multi-turn, 6 parallel tool calls, tracing, cost. The Groq model to use.
Azure / vLLM / other OpenAI-compatible via base_urlDepends entirely on whether the served model enforces schemas

Models without native JSON-schema output. On the default path these fail on the first turn — it isn’t a degraded mode, nothing usable comes back.

ModelNative failure
groq/llama-3.3-70b-versatileBadRequestError … tool_use_failed (verified)

Most small local models fall in this tier.

They can still be driven through the prompted fallback:

minions.Minion(model="groq/llama-3.3-70b-versatile", structured_output="prompt", tools=[...])

This puts the schema and a worked example in the system prompt, asks for json_object mode, and re-prompts on a malformed reply (bounded by max_parse_retries, default 2). Nothing enforces the shape, so it is a weaker guarantee than Tier 1 — expect the occasional wasted turn, and expect it to cost slightly more, since a reparse is a real extra call whose tokens are charged to that turn.

It is not the default for exactly that reason. Treat it as “this model can be made to work”, not “this model is supported”.

For a model without schema support, LiteLLM emulates structured output by wrapping the schema in a synthetic function called json_tool_call. llama-3.3-70b then generated arguments for one tool instead of the required envelope, and Groq’s server-side validation rejected its own generation:

litellm.BadRequestError: GroqException - tool call validation failed:
parameters for tool json_tool_call did not match schema:
missing properties: 'next_thought', 'next_tools',
additionalProperties 'tool_name', 'args' not allowed
failed_generation: <function=json_tool_call>{"tool_name": "get_population",
"args": [{"key": "city", "value": "Tokyo"}]}

The model understood the task — it did want to look up Tokyo — but couldn’t hold the nested shape.

Honest accounting of what has actually been run:

ModelVerified
groq/openai/gpt-oss-120b✅ live run, passed — see the caveat below
groq/llama-3.3-70b-versatile✅ live: fails natively as documented, and succeeds via structured_output="prompt" — multi-turn, six parallel tool calls in one turn
groq/moonshotai/kimi-k2-instruct⬜ untested — no account access. supports_response_schema reports False, so Tier 3 is expected, not confirmed
OpenAI, Anthropic, Gemini⬜ not yet covered by an automated test pass, despite being Tier 1

Caveat: intermittent tool_use_failed on Groq

Section titled “Caveat: intermittent tool_use_failed on Groq”

groq/openai/gpt-oss-120b occasionally emits a native function call instead of the required envelope — having seen your tool names described in the prompt, it reaches for the provider’s own function-calling — and Groq then rejects its own generation:

{"error":{"message":"Tool choice is none, but model called a tool",
"code":"tool_use_failed",
"failed_generation":"{\"name\": \"search_code\", ...}"}}

The same model, prompt and tools succeed on the next attempt, so this is not a capability limit. Minion retries a rejected request up to max_parse_retries times before concluding a model can’t do structured output, which absorbs it. Worth knowing if you see it in a trace.

Closing that last gap — a scripted smoke test across the three Tier 1 providers — is a pre-launch blocker.

  • Use groq/openai/gpt-oss-120b; it supports both JSON-schema output and reasoning_effort.
  • The environment variable must be GROQ_API_KEY exactly. LiteLLM will not pick up a suffixed name like GROQ_API_KEY_1.
  • The free tier allows 8,000 tokens per minute. That is small enough to matter: a sub-agent fan-out spends several times it in one burst and every call in that burst fails with RateLimitError. Check your own headroom with x-ratelimit-limit-tokens / x-ratelimit-remaining-tokens on any response. Single-agent runs with small tool returns fit comfortably; delegation does not.
  • Groq prices are in the built-in table for gpt-oss-120b, gpt-oss-20b, llama-3.3-70b-versatile and llama-3.1-8b-instant. Other Groq models show as unpriced until you add a custom price.

Azure OpenAI, vLLM, and any OpenAI-compatible gateway work through base_url:

minions.init(api_key="...", base_url="https://my-gateway.internal/v1")

Whether it works comes down to one thing: does the served model enforce the response schema? A gateway that accepts response_format and ignores it will fail the same way a Tier 3 model does.

litellm.drop_params = True is set globally, so parameters a model doesn’t support (for example reasoning_effort on a model without reasoning) are dropped silently rather than raising. This keeps one Minion config portable across models — at the cost of a silently ignored setting, so don’t assume a parameter took effect just because the call succeeded.

The provider error underneath is unhelpful on its own, so Minion translates it. Instead of a raw BadRequestError you get a minions.structured_output.StructuredOutputError naming the model, explaining what was asked for, and listing the ways forward — with the provider’s original message appended for anyone who needs it:

The model 'groq/llama-3.3-70b-versatile' could not produce the structured
output Minion needs.
Every turn, Minion asks for a strict JSON object -- a thought plus the tools
to call next. This model's provider does not enforce that schema, so the
model returned something else and the provider rejected it.
What to do:
1. Check the model: litellm.supports_response_schema(model='...')
2. Use a Tier 1 model (OpenAI, Anthropic, Gemini), or a Tier 2 model that
supports native JSON-schema output.
3. Or retry this model with the prompted fallback:
Minion(..., structured_output="prompt")
...

An error that is not about structured output — a bad API key, a rate limit — propagates unchanged. Minion doesn’t claim every failure is a schema problem.