> ## Documentation Index
> Fetch the complete documentation index at: https://docs.parallel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Fireworks

> Ground Fireworks-hosted open models in live web results with Parallel Search

For AI agents: a documentation index is available at [https://docs.parallel.ai/llms.txt](https://docs.parallel.ai/llms.txt). The full text of all docs is at [https://docs.parallel.ai/llms-full.txt](https://docs.parallel.ai/llms-full.txt). You may also fetch any page as Markdown by appending `.md` to its URL or sending `Accept: text/markdown`.

For Search and Extract, use `/v1/search` and `/v1/extract` for all new integrations and agent tool calls. Use `/v1beta/search` and `/v1beta/extract` only when maintaining an existing integration that already uses them. The request bodies changed too: on `/v1/extract`, `full_content`, `fetch_policy` and `excerpt_settings` go inside `advanced_settings`, and sending the v1beta top-level `excerpts`, `full_content` and `fetch_policy` to `/v1/extract` returns a 422. Do not substitute `/v1` for the documented FindAll or Ingest endpoint paths.

[Fireworks](https://fireworks.ai) serves open models through an OpenAI-compatible API. This guide shows how to give a Fireworks model a `web_search` tool backed by Parallel Search, so it can answer questions about current topics and cite its sources.

The example is a small search app in a single file. You ask a question, the model searches the web with Parallel, and you get back an answer with source URLs.

## How it works

1. You send a question to a Fireworks model through the [chat completions API](https://docs.fireworks.ai/guides/querying-text-models), along with a `web_search` tool definition.
2. The model decides it needs fresh information and returns a tool call with a search objective and a few keyword queries.
3. Your code sends the objective and queries to Parallel Search at `POST https://api.parallel.ai/v1/search`.
4. You return the search results to the model as a tool message.
5. The model writes a final answer from the results and lists the URLs it used.

The model can search more than once before it answers. The example stops after five model calls.

## What you'll need

* A [Fireworks API key](https://app.fireworks.ai/settings/users/api-keys), exported as `FIREWORKS_API_KEY`.
* A [Parallel API key](https://platform.parallel.ai), exported as `PARALLEL_API_KEY`.
* Python 3.10 or later. For the TypeScript version, Node.js 22 or later.

## Install

```bash Python theme={"system"}
pip install openai requests
export FIREWORKS_API_KEY="your-fireworks-api-key"
export PARALLEL_API_KEY="your-parallel-api-key"
```

```bash TypeScript theme={"system"}
npm install openai
export FIREWORKS_API_KEY="your-fireworks-api-key"
export PARALLEL_API_KEY="your-parallel-api-key"
```

The example uses the OpenAI SDK because Fireworks is [OpenAI-compatible](https://docs.fireworks.ai/tools-sdks/openai-compatibility). It calls Parallel Search over plain HTTP, so you don't need the Parallel SDK.

## Build the search app

Save the Python version as `search_app.py` and run it with `python search_app.py`. Save the TypeScript version as `search_app.ts` and run it with `npx tsx search_app.ts`.

```python Python theme={"system"}
import json
import os
import uuid

import requests
from openai import OpenAI

MODEL = "accounts/fireworks/models/kimi-k3"

fireworks = OpenAI(
    api_key=os.environ["FIREWORKS_API_KEY"],
    base_url="https://api.fireworks.ai/inference/v1",
)

SEARCH_TOOL = {
    "type": "function",
    "function": {
        "name": "web_search",
        "description": "Search the web and return result titles, URLs, and excerpts.",
        "parameters": {
            "type": "object",
            "properties": {
                "objective": {
                    "type": "string",
                    "description": "Describe the search goal in a concise, standalone sentence. Name the key entity or topic.",
                },
                "search_queries": {
                    "type": "array",
                    "description": "Provide 1-3 keyword queries of 3-6 words each. Include the key entity or topic in every query. For multiple queries, vary names, synonyms, or angles. Do not use sentences, instructions, or site: operators.",
                    "items": {"type": "string"},
                    "minItems": 1,
                    "maxItems": 3,
                },
            },
            "required": ["objective", "search_queries"],
        },
    },
}

SYSTEM_PROMPT = (
    "Use the web_search tool to find current information before you answer. "
    "Answer in a few sentences, then end with a Sources list of the URLs you used."
)


def web_search(objective, search_queries, session_id):
    response = requests.post(
        "https://api.parallel.ai/v1/search",
        headers={"x-api-key": os.environ["PARALLEL_API_KEY"]},
        json={
            "objective": objective,
            "search_queries": search_queries,
            "session_id": session_id,
            "mode": "fast",
            "advanced_settings": {"max_results": 5},
        },
        timeout=60,
    )
    response.raise_for_status()
    return response.json()["results"]


def answer(question, max_steps=5):
    session_id = f"session_{uuid.uuid4().hex}"
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": question},
    ]
    for _ in range(max_steps):
        response = fireworks.chat.completions.create(
            model=MODEL,
            messages=messages,
            tools=[SEARCH_TOOL],
            temperature=0.1,
        )
        message = response.choices[0].message
        if not message.tool_calls:
            return message.content
        messages.append(message)
        for tool_call in message.tool_calls:
            args = json.loads(tool_call.function.arguments)
            results = web_search(args["objective"], args["search_queries"], session_id)
            messages.append(
                {
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": json.dumps(results),
                }
            )
    raise RuntimeError("The model did not finish answering within max_steps.")


if __name__ == "__main__":
    print(answer("What is the latest stable release of Python, and what is new in it?"))
```

```typescript TypeScript theme={"system"}
import OpenAI from "openai";

const MODEL = "accounts/fireworks/models/kimi-k3";

const fireworks = new OpenAI({
  apiKey: process.env.FIREWORKS_API_KEY,
  baseURL: "https://api.fireworks.ai/inference/v1",
});

const searchTool: OpenAI.ChatCompletionTool = {
  type: "function",
  function: {
    name: "web_search",
    description: "Search the web and return result titles, URLs, and excerpts.",
    parameters: {
      type: "object",
      properties: {
        objective: {
          type: "string",
          description:
            "Describe the search goal in a concise, standalone sentence. Name the key entity or topic.",
        },
        search_queries: {
          type: "array",
          description:
            "Provide 1-3 keyword queries of 3-6 words each. Include the key entity or topic in every query. For multiple queries, vary names, synonyms, or angles. Do not use sentences, instructions, or site: operators.",
          items: { type: "string" },
          minItems: 1,
          maxItems: 3,
        },
      },
      required: ["objective", "search_queries"],
    },
  },
};

const SYSTEM_PROMPT =
  "Use the web_search tool to find current information before you answer. " +
  "Answer in a few sentences, then end with a Sources list of the URLs you used.";

async function webSearch(objective: string, searchQueries: string[], sessionId: string) {
  const response = await fetch("https://api.parallel.ai/v1/search", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "x-api-key": process.env.PARALLEL_API_KEY ?? "",
    },
    body: JSON.stringify({
      objective,
      search_queries: searchQueries,
      session_id: sessionId,
      mode: "fast",
      advanced_settings: { max_results: 5 },
    }),
  });
  if (!response.ok) {
    throw new Error(`Parallel Search failed: ${response.status} ${await response.text()}`);
  }
  const data = await response.json();
  return data.results;
}

async function answer(question: string, maxSteps = 5): Promise<string | null> {
  const sessionId = `session_${crypto.randomUUID()}`;
  const messages: OpenAI.ChatCompletionMessageParam[] = [
    { role: "system", content: SYSTEM_PROMPT },
    { role: "user", content: question },
  ];
  for (let step = 0; step < maxSteps; step++) {
    const response = await fireworks.chat.completions.create({
      model: MODEL,
      messages,
      tools: [searchTool],
      temperature: 0.1,
    });
    const message = response.choices[0].message;
    if (!message.tool_calls?.length) {
      return message.content;
    }
    messages.push(message);
    for (const toolCall of message.tool_calls) {
      if (toolCall.type !== "function") {
        continue;
      }
      const args = JSON.parse(toolCall.function.arguments);
      const results = await webSearch(args.objective, args.search_queries, sessionId);
      messages.push({
        role: "tool",
        tool_call_id: toolCall.id,
        content: JSON.stringify(results),
      });
    }
  }
  throw new Error("The model did not finish answering within maxSteps.");
}

answer("What is the latest stable release of Python, and what is new in it?").then(console.log);
```

The example uses Kimi K3 (`accounts/fireworks/models/kimi-k3`), which Fireworks lists as a recommended model for agents with tool use. You can switch to any Fireworks model that supports function calling by changing `MODEL`.

## Example output

When the model decides to search, its tool call arguments look like this:

```json theme={"system"}
{
  "objective": "Find the latest stable Python release and what is new in it.",
  "search_queries": [
    "latest Python stable release",
    "Python release new features",
    "Python whats new"
  ]
}
```

Parallel Search returns results ordered by relevance. Each result has a `url`, `title`, `publish_date`, and `excerpts`. The app passes the `results` array to the model unchanged:

```json theme={"system"}
[
  {
    "url": "https://www.python.org/downloads/release/python-3150",
    "title": "Python Release Python 3.15.0 | Python.org",
    "publish_date": null,
    "excerpts": [
      "**Release date:** Oct. 9, 2026\n\nPython 3.15.0 is the newest major release ..."
    ]
  }
]
```

The full Search response also includes `search_id`, `session_id`, `warnings`, and `usage`. See the [Search API reference](https://docs.parallel.ai/api-reference/search/search.md) for every field.

The final answer is plain text that ends with the sources the model used:

```text theme={"system"}
<A short answer written from the search results.>

Sources:
- https://www.python.org/downloads/release/python-3150
- https://blog.python.org/2026/10/python-3150-final-is-here
```

## Tips

* **Choose a model that supports function calling.** Not every Fireworks model supports tools. Look for Function Calling on the model's page in the [Fireworks Model Library](https://app.fireworks.ai/models), or see Fireworks' [recommended models](https://docs.fireworks.ai/guides/recommended-models) for agents with tool use. Fireworks also recommends a low temperature, between 0.0 and 0.3, for tool calling.
* **Pass the assistant message back as is.** Reasoning models on Fireworks can return `reasoning_content` alongside tool calls. Appending the SDK message object keeps that context for the next call. See [interleaved thinking](https://docs.fireworks.ai/guides/reasoning#interleaved-thinking) in the Fireworks docs.
* **Pick a Search mode.** The example uses `fast`, which returns high-quality results in around 700ms and suits most tool-calling loops. Use `turbo` for the lowest latency and cost. Leave out `mode` to use the default `advanced` mode when quality matters more than speed. See [Search modes](https://docs.parallel.ai/search/modes.md).
* **Set the result count.** `advanced_settings.max_results` sets the maximum number of results. It defaults to 10 and Search returns at most 20. Fewer results keep the model's context small. See [Advanced settings](https://docs.parallel.ai/search/advanced-search-settings.md).
* **Reuse one session per question.** The example creates a `session_id` for each question and sends it with every search for that question. This groups related calls, as described in [Search best practices](https://docs.parallel.ai/search/best-practices.md#session-identifiers).
* **Cite sources.** Every result includes its `url`, and the system prompt asks the model to list the URLs it used. If your app needs a guaranteed source list, also collect the URLs from the search results in your code.

## Costs

You pay Fireworks for model tokens and Parallel for each search. See [Fireworks serverless pricing](https://docs.fireworks.ai/serverless/pricing) and [Parallel pricing](https://docs.parallel.ai/getting-started/pricing.md). Search pricing depends on the mode, and each tool call is one search request.

## Next steps

* [Extract](https://docs.parallel.ai/extract/extract-quickstart.md): add a second tool so the model can read full pages or focused excerpts from URLs it finds.
* [Search MCP](https://docs.parallel.ai/integrations/mcp/search-mcp.md): connect Parallel Search and Extract to an MCP client without writing a tool handler.
* [Search best practices](https://docs.parallel.ai/search/best-practices.md): write better objectives and search queries.
* Fireworks docs: [tool calling](https://docs.fireworks.ai/guides/function-calling), [OpenAI compatibility](https://docs.fireworks.ai/tools-sdks/openai-compatibility), and the [serverless quickstart](https://docs.fireworks.ai/getting-started/quickstart).
