Skip to content

feat(cerebras): add chat language model provider#15420

Merged
gr2m merged 8 commits into
mainfrom
aayush/cerebras-language-model
May 19, 2026
Merged

feat(cerebras): add chat language model provider#15420
gr2m merged 8 commits into
mainfrom
aayush/cerebras-language-model

Conversation

@aayush-kapoor
Copy link
Copy Markdown
Collaborator

Background

#15349

this is a follow up to #15416.

cerebras models could return a valid structured JSON answer, like {"result":"2026"}, while also marking the response as tool_calls and repeating a tool call in the same response. The AI SDK interpreted that as “keep calling tools,” so the loop continued until stopWhen was hit. Because the final step still had finish reason tool-calls, result.output was never parsed and threw NoOutputGeneratedError

Summary

  • Added a CerebrasChatLanguageModel wrapper around the OpenAI-compatible chat model
  • For structured JSON output calls only, when cerebras returns non-empty text with raw finish reason tool_calls, we treat it as the final structured answer
  • In that narrow case, we normalize the finish reason to stop and drop the stray repeated tool-call part
  • Real tool-call turns without text are still preserved and executed normally

what would have been a bug fix was treated as an opportunity to handle cerebras quirks specifically

Manual Verification

verified by running the repro:

import { NoOutputGeneratedError, Output, isStepCount, tool, ToolLoopAgent } from "ai";
import z from "zod";
import { cerebras } from "@ai-sdk/cerebras";
import { run } from '../../lib/run';

run(async () => {
  const agent = new ToolLoopAgent({
    instructions:
      "Use the required structured output. For simple arithmetic you may answer directly.",
    model: cerebras("zai-glm-4.7"),
    tools: {
      nonUsefulTool: tool({
        description: "A non-useful tool that returns a magic number",
        inputSchema: z.object({}),
        execute: () => {
          return 2026;
        },
      }),
    },
    output: Output.object({
      schema: z.object({ result: z.string() }),
    }),
    stopWhen: isStepCount(5),
  });
  const result = await agent.generate({
    prompt: "what is the magic number?",
  });

  console.log(
    'steps:',
    JSON.stringify(
      result.steps.map(step => ({
        finishReason: step.finishReason,
        text: step.text,
        toolCalls: step.toolCalls.map(toolCall => ({
          toolName: toolCall.toolName,
          input: toolCall.input,
        })),
      })),
      null,
      2,
    ),
  );

  try {
    console.log(result.output);
  } catch (cause) {
    if (NoOutputGeneratedError.isInstance(cause)) {
      console.error(
        "Structured output missing (last step did not yield valid JSON).",
        "finishReason:",
        result.finishReason,
        "lastText:",
        JSON.stringify(result.text),
      );
      throw cause;
    }
    throw cause;
  }
});

Checklist

  • All commits are signed (PRs with unsigned commits cannot be merged)
  • Tests have been added / updated (for bug fixes / features)
  • Documentation has been added / updated (for bug fixes / features)
  • A patch changeset for relevant packages has been added (for bug fixes / features - run pnpm changeset in the project root)
  • I have reviewed this pull request (self-review)

Related Issues

fixes #15349

Comment thread packages/cerebras/src/cerebras-chat-language-model.ts Outdated
@gr2m gr2m merged commit 63f29e0 into main May 19, 2026
48 checks passed
@gr2m gr2m deleted the aayush/cerebras-language-model branch May 19, 2026 03:43
@aayush-kapoor aayush-kapoor added the backport Admins only: add this label to a pull request in order to backport it to the prior version label May 19, 2026
github-actions Bot added a commit that referenced this pull request May 19, 2026
## Background

#15349

this is a follow up to #15416. 

cerebras models could return a valid structured JSON answer, like
{"result":"2026"}, while also marking the response as `tool_calls` and
repeating a tool call in the same response. The AI SDK interpreted that
as “keep calling tools,” so the loop continued until stopWhen was hit.
Because the final step still had finish reason `tool-calls`,
`result.output` was never parsed and threw `NoOutputGeneratedError`

## Summary

- Added a CerebrasChatLanguageModel wrapper around the OpenAI-compatible
chat model
- For structured JSON output calls only, when cerebras returns non-empty
text with raw finish reason `tool_calls`, we treat it as the final
structured answer
- In that narrow case, we normalize the finish reason to `stop` and drop
the stray repeated tool-call part
- Real tool-call turns without text are still preserved and executed
normally

what would have been a bug fix was treated as an opportunity to handle
cerebras quirks specifically

## Manual Verification

verified by running the repro: 

```ts
import { NoOutputGeneratedError, Output, isStepCount, tool, ToolLoopAgent } from "ai";
import z from "zod";
import { cerebras } from "@ai-sdk/cerebras";
import { run } from '../../lib/run';

run(async () => {
  const agent = new ToolLoopAgent({
    instructions:
      "Use the required structured output. For simple arithmetic you may answer directly.",
    model: cerebras("zai-glm-4.7"),
    tools: {
      nonUsefulTool: tool({
        description: "A non-useful tool that returns a magic number",
        inputSchema: z.object({}),
        execute: () => {
          return 2026;
        },
      }),
    },
    output: Output.object({
      schema: z.object({ result: z.string() }),
    }),
    stopWhen: isStepCount(5),
  });
  const result = await agent.generate({
    prompt: "what is the magic number?",
  });

  console.log(
    'steps:',
    JSON.stringify(
      result.steps.map(step => ({
        finishReason: step.finishReason,
        text: step.text,
        toolCalls: step.toolCalls.map(toolCall => ({
          toolName: toolCall.toolName,
          input: toolCall.input,
        })),
      })),
      null,
      2,
    ),
  );

  try {
    console.log(result.output);
  } catch (cause) {
    if (NoOutputGeneratedError.isInstance(cause)) {
      console.error(
        "Structured output missing (last step did not yield valid JSON).",
        "finishReason:",
        result.finishReason,
        "lastText:",
        JSON.stringify(result.text),
      );
      throw cause;
    }
    throw cause;
  }
});
```

## Checklist

- [x] All commits are signed (PRs with unsigned commits cannot be
merged)
- [x] Tests have been added / updated (for bug fixes / features)
- [ ] Documentation has been added / updated (for bug fixes / features)
- [x] A _patch_ changeset for relevant packages has been added (for bug
fixes / features - run `pnpm changeset` in the project root)
- [x] I have reviewed this pull request (self-review) 

## Related Issues

fixes #15349

---------

Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
@github-actions github-actions Bot removed the backport Admins only: add this label to a pull request in order to backport it to the prior version label May 19, 2026
@github-actions
Copy link
Copy Markdown
Contributor

✅ Backport PR created: #15428

gr2m added a commit that referenced this pull request May 19, 2026
## Background

#15349

this is a follow up to #15416. 

cerebras models could return a valid structured JSON answer, like
{"result":"2026"}, while also marking the response as `tool_calls` and
repeating a tool call in the same response. The AI SDK interpreted that
as “keep calling tools,” so the loop continued until stopWhen was hit.
Because the final step still had finish reason `tool-calls`,
`result.output` was never parsed and threw `NoOutputGeneratedError`

## Summary

- Added a CerebrasChatLanguageModel wrapper around the OpenAI-compatible
chat model
- For structured JSON output calls only, when cerebras returns non-empty
text with raw finish reason `tool_calls`, we treat it as the final
structured answer
- In that narrow case, we normalize the finish reason to `stop` and drop
the stray repeated tool-call part
- Real tool-call turns without text are still preserved and executed
normally

what would have been a bug fix was treated as an opportunity to handle
cerebras quirks specifically

## Manual Verification

verified by running the repro: 

```ts
import { NoOutputGeneratedError, Output, isStepCount, tool, ToolLoopAgent } from "ai";
import z from "zod";
import { cerebras } from "@ai-sdk/cerebras";
import { run } from '../../lib/run';

run(async () => {
  const agent = new ToolLoopAgent({
    instructions:
      "Use the required structured output. For simple arithmetic you may answer directly.",
    model: cerebras("zai-glm-4.7"),
    tools: {
      nonUsefulTool: tool({
        description: "A non-useful tool that returns a magic number",
        inputSchema: z.object({}),
        execute: () => {
          return 2026;
        },
      }),
    },
    output: Output.object({
      schema: z.object({ result: z.string() }),
    }),
    stopWhen: isStepCount(5),
  });
  const result = await agent.generate({
    prompt: "what is the magic number?",
  });

  console.log(
    'steps:',
    JSON.stringify(
      result.steps.map(step => ({
        finishReason: step.finishReason,
        text: step.text,
        toolCalls: step.toolCalls.map(toolCall => ({
          toolName: toolCall.toolName,
          input: toolCall.input,
        })),
      })),
      null,
      2,
    ),
  );

  try {
    console.log(result.output);
  } catch (cause) {
    if (NoOutputGeneratedError.isInstance(cause)) {
      console.error(
        "Structured output missing (last step did not yield valid JSON).",
        "finishReason:",
        result.finishReason,
        "lastText:",
        JSON.stringify(result.text),
      );
      throw cause;
    }
    throw cause;
  }
});
```

## Checklist

- [x] All commits are signed (PRs with unsigned commits cannot be
merged)
- [x] Tests have been added / updated (for bug fixes / features)
- [ ] Documentation has been added / updated (for bug fixes / features)
- [x] A _patch_ changeset for relevant packages has been added (for bug
fixes / features - run `pnpm changeset` in the project root)
- [x] I have reviewed this pull request (self-review) 

## Related Issues

fixes #15349

---------

Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
github-actions Bot added a commit that referenced this pull request May 19, 2026
This is an automated backport of #15420 to the release-v6.0 branch. FYI
@aayush-kapoor

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
Co-authored-by: Aayush Kapoor <aayushkapoor34@gmail.com>
aayush-kapoor added a commit that referenced this pull request May 19, 2026
…15427)

## Background

observed in #15420; when creating a new
language model file, it is now important to account for workflow
serialization and deserialization (serde). this was highlighted by the
vercel agent in
#15420 (comment)

so it makes sense to include it as rule

## Summary

added a new rule that which ensures provider language model files must
import the helpers/symbols needed to serialize and deserialize model
instances across workflow step boundaries

## Manual Verification

na

## Checklist

- [x] All commits are signed (PRs with unsigned commits cannot be
merged)
- [x] Tests have been added / updated (for bug fixes / features)
- [ ] Documentation has been added / updated (for bug fixes / features)
- [x] A _patch_ changeset for relevant packages has been added (for bug
fixes / features - run `pnpm changeset` in the project root)
- [x] I have reviewed this pull request (self-review)

---------

Co-authored-by: Felix Arntz <felix.arntz@vercel.com>
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Published in:

Package Version
ai 7.0.0-canary.144 github npm
@ai-sdk/alibaba 2.0.0-canary.52 github npm
@ai-sdk/amazon-bedrock 5.0.0-canary.65 github npm
@ai-sdk/angular 3.0.0-canary.144 github npm
@ai-sdk/anthropic 4.0.0-canary.57 github npm
@ai-sdk/assemblyai 3.0.0-canary.45 github npm
@ai-sdk/azure 4.0.0-canary.61 github npm
@ai-sdk/baseten 2.0.0-canary.50 github npm
@ai-sdk/black-forest-labs 2.0.0-canary.44 github npm
@ai-sdk/bytedance 2.0.0-canary.45 github npm
@ai-sdk/cerebras 3.0.0-canary.50 github npm
@ai-sdk/codemod 4.0.0-canary.6 github npm
@ai-sdk/cohere 4.0.0-canary.47 github npm
@ai-sdk/deepgram 3.0.0-canary.44 github npm
@ai-sdk/deepinfra 3.0.0-canary.50 github npm
@ai-sdk/deepseek 3.0.0-canary.48 github npm
@ai-sdk/devtools 1.0.0-canary.26 github npm
@ai-sdk/elevenlabs 3.0.0-canary.44 github npm
@ai-sdk/fal 3.0.0-canary.44 github npm
@ai-sdk/fireworks 3.0.0-canary.50 github npm
@ai-sdk/gateway 4.0.0-canary.85 github npm
@ai-sdk/gladia 3.0.0-canary.44 github npm
@ai-sdk/google 4.0.0-canary.67 github npm
@ai-sdk/google-vertex 5.0.0-canary.86 github npm
@ai-sdk/groq 4.0.0-canary.47 github npm
@ai-sdk/huggingface 2.0.0-canary.50 github npm
@ai-sdk/hume 3.0.0-canary.44 github npm
@ai-sdk/klingai 4.0.0-canary.45 github npm
@ai-sdk/langchain 3.0.0-canary.144 github npm
@ai-sdk/llamaindex 3.0.0-canary.144 github npm
@ai-sdk/lmnt 3.0.0-canary.44 github npm
@ai-sdk/luma 3.0.0-canary.44 github npm
@ai-sdk/mcp 2.0.0-canary.52 github npm
@ai-sdk/mistral 4.0.0-canary.49 github npm
@ai-sdk/moonshotai 3.0.0-canary.50 github npm
@ai-sdk/open-responses 2.0.0-canary.47 github npm
@ai-sdk/openai 4.0.0-canary.61 github npm
@ai-sdk/openai-compatible 3.0.0-canary.50 github npm
@ai-sdk/otel 1.0.0-canary.90 github npm
@ai-sdk/perplexity 4.0.0-canary.47 github npm
@ai-sdk/prodia 2.0.0-canary.47 github npm
@ai-sdk/provider 4.0.0-canary.17 github npm
@ai-sdk/provider-utils 5.0.0-canary.43 github npm
@ai-sdk/react 4.0.0-canary.145 github npm
@ai-sdk/replicate 3.0.0-canary.45 github npm
@ai-sdk/revai 3.0.0-canary.45 github npm
@ai-sdk/rsc 3.0.0-canary.145 github npm
@ai-sdk/svelte 5.0.0-canary.144 github npm
@ai-sdk/test-server 2.0.0-canary.6 github npm
@ai-sdk/togetherai 3.0.0-canary.50 github npm
@ai-sdk/valibot 3.0.0-canary.43 github npm
@ai-sdk/vercel 3.0.0-canary.50 github npm
@ai-sdk/voyage 2.0.0-canary.18 github npm
@ai-sdk/vue 4.0.0-canary.144 github npm
@ai-sdk/workflow 1.0.0-canary.61 github npm
@ai-sdk/xai 4.0.0-canary.66 github npm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[@ai-sdk/cerebras] Cerebras does not work with tools + structured output

2 participants