Muse Spark Structured Outputs and Tool Calling: What the Docs Say
How JSON schema output and function calling work on the Meta Model API for Muse Spark: parameters, strict mode, limits, parallel calls and tool search.
Muse Spark supports structured outputs by setting response_format to type: "json_schema" on Chat Completions, or text.format on the Responses API, and it supports tool calling through a standard tools array with parallel calls on by default. Both follow OpenAI's request shapes on the Meta Model API, with a few differences worth knowing: strict mode is off by default, tool_choice only accepts "auto", and recursive schemas are rejected.
This post sticks to what Meta documents at dev.meta.ai/docs/structured-output and dev.meta.ai/docs/tool-calling. Where the docs are silent, we say so.
Which API formats support structured output?
The Meta Model API lives at https://api.meta.ai/v1 and is "drop-in compatible" with the OpenAI SDK, the Anthropic SDK and OpenAI-compatible CLIs. It accepts Responses, Chat Completions and Messages formats, authenticated with a Bearer MODEL_API_KEY (docs).
Structured output is documented for:
- Chat Completions (
/v1/chat/completions):response_formatwithtype: "json_schema"and your schema in thejson_schemafield.json_schema.strictdefaults tofalse. - Responses API:
text.format, the equivalent ofresponse_format.text.format.strictalso defaults tofalse. - OpenAI SDK helpers:
beta.chat.completions.parse()with Pydantic models.
The structured output page does not describe an Anthropic Messages equivalent. If you use the Anthropic SDK against Meta's endpoint, test before relying on it.
A minimal structured output request
Using the OpenAI Python SDK pointed at Meta's base URL:
from openai import OpenAI
from pydantic import BaseModel
client = OpenAI(base_url="https://api.meta.ai/v1", api_key=MODEL_API_KEY)
class Invoice(BaseModel):
vendor: str
total: float
due_date: str
resp = client.beta.chat.completions.parse(
model="muse-spark-1.3",
messages=[{"role": "user", "content": invoice_text}],
response_format=Invoice,
)
print(resp.choices[0].message.parsed)
The model ID and base URL come from Meta's overview page; the parse() helper is the one Meta's structured output page names.
Strict mode rules
Setting strict: true makes the server validate your schema against a stricter subset. Per the docs:
- The root must be a plain object. No
anyOf,oneOf,allOf,enumornotat the top level. allOfandoneOfare not supported anywhere;anyOfis allowed only below the root.- Every object must set
additionalProperties: false. - The
requiredarray must list every key inproperties.
The last rule trips people up. In OpenAI-style strict schemas, optional fields are usually written as required fields that accept null. Meta's page does not show an example of that pattern, so test it against your schema.
Schema size limits
| Constraint | Limit |
|---|---|
| Nesting depth | 10 levels |
| Total properties | 5,000 across the schema |
| Total string length | 120,000 characters |
| Enum values | 1,000 |
| Recursive schemas | Not supported |
Source: structured output docs. No recursion means tree-shaped data like nested comments or org charts needs flattening into a list with parent IDs.
How tool calling works on Muse Spark
The tool-calling page documents these parameters:
tools: an array of function (or custom) tool definitions. Responses API uses a flat shape (type,name,description,parameters); Chat Completions nests them underfunction.tool_choice: only"auto"is supported. Any other value returns HTTP 400. You cannot force a specific tool call.parallel_tool_calls: defaults totrue. Set it tofalsefor one call per turn.stricton a tool: validates the parameter schema against the strict subset, same rules as above.max_tool_calls: caps built-in tool calls only, minimum 1. It does not limit your own function tools.
Two naming rules to validate client-side: function names must match ^[a-zA-Z0-9_.-]+$ with at most one dot, and call_id must be 1 to 64 characters.
Streaming tool arguments
With stream: true, arguments stream incrementally. On Chat Completions you accumulate deltas by tool-call index; on the Responses API you consume function_call_arguments.delta events. Meta's overview lists parallel tool calls with streamed arguments as a native primitive.
Some third-party harnesses tripped on Muse Spark's streaming. muse-spark-anywhere is a set of fixes that handle a non-standard SSE event and missing model-catalog entries so Spark runs in pi, opencode and Agent Orchestrator. If your client chokes on the stream, look there first.
Tool search for large toolsets
If you have many tools, mark them defer_loading: true and add the tool_search tool. The model then loads only the tools it needs, which Meta says saves tokens. This matters for agents that wrap dozens of connectors; the 150 one-paste connector skills collection is the kind of toolset where loading everything up front would be wasteful.
What about Muse Glimmer?
Glimmer is self-hosted, so structured output depends on your server, not Meta's API. Builders note Glimmer emits its own tool-call format: the zero-backend agent console renders Glimmer's "ATEM" tool-call format client-side. vLLM and SGLang had day-0 Glimmer support, and their own structured-generation features apply. Meta's model card reports 75.5 on MCP Atlas, a tool-use benchmark (model card).
A good example of structured output in practice is dealscan, which uses Glimmer to read music contracts and emits a markdown and JSON report of payment terms and risky clauses.
Costs and limits to keep in mind
Standard tier Muse Spark costs $1.25 per million input tokens and $4.25 output; the contributor tier is $0.10 and $0.20 but Meta may train on the data. Rate limits are 3,000 RPM and 4M TPM per team on standard, 100 RPM and 3M TPM on contributor (pricing). Long JSON schemas count as input tokens on every call, so prompt caching ($0.15 per million cached input) helps if the schema is a stable prefix.
For the rest of the developer stack, see the Muse developer platform overview. Browse tools and apps for more API builds.
Frequently asked questions
Does Muse Spark support JSON mode?
Yes, through JSON schema structured output: response_format with type: "json_schema" on Chat Completions or text.format on the Responses API. Strict validation is off unless you set strict: true.
Can I force Muse Spark to call a specific tool?
No. The docs say tool_choice only supports "auto", and other values return HTTP 400. Steer tool use through the system prompt and tool descriptions instead.
Does Muse Spark support parallel function calling?
Yes, and it is on by default. Set parallel_tool_calls to false to limit the model to one call per turn.
Are recursive JSON schemas supported?
No. Meta's docs state recursive schemas are not supported, and schemas are limited to 10 levels of nesting and 5,000 properties. Flatten recursive data into lists with parent references.
Can I use the OpenAI SDK with Muse Spark?
Yes. Point the OpenAI SDK at https://api.meta.ai/v1 with your Meta API key. Meta's structured output docs reference the SDK's beta.chat.completions.parse() helper with Pydantic models.
Numbers throughout are as reported by the build authors or by Meta, not verified by shipwithmuse. Official documentation lives at muse.ai/platform.
ChatForm
Tgmlabs