> SpecStream is the live web data engine for teams and agents. This is the Markdown copy of https://specstream.ai/docs/integrations/gemini-live-api. Every page, with what SpecStream does and costs: https://specstream.ai/llms.txt

# Gemini Live API

Give a Gemini Live voice session a web search it calls as a function. The SpecStream Search API answers with the fact, the page it was read from and the ranked results. The model speaks the answer, and your code keeps every source URL.

[SpecStream for Gemini Live APIAgent frameworks & builders](https://specstream.ai/integrations/gemini-live-api.md)

## What you need

-   A Gemini API key, Python with the Google Gen AI SDK and httpx (`pip install google-genai httpx`).
-   A SpecStream API key. New accounts start with $10 of credit, no card. [Create an account](https://specstream.ai/signup?utm_source=gemini-live-api).

1.  1

    ## 1. Create a SpecStream API key

    In SpecStream, open [Agents & API](https://specstream.ai/workspace/agents?tab=keys&utm_source=gemini-live-api), choose **API keys**, then **Create API key**. Give it execute permission and a spending limit above zero, so it can search. Set it as `SPECSTREAM_API_KEY` on the server that runs your session. Keep the key on the server and out of the browser.

2.  2

    ## 2. Declare the search function

    The Live API takes your functions as `function_declarations` in the session config. Declare one that takes the question. Add each block of this guide to one file, `live_search.py`, in order:

    live\_search.py

    ```python
    web_search = {
        "name": "web_search",
        "description": "Search the live web. Use it for news, prices, schedules and any fact that may have changed since training.",
        "parameters": {
            "type": "object",
            "properties": {
                "q": {"type": "string", "description": "The question, in everyday words"}
            },
            "required": ["q"],
        },
    }
    tools = [{"function_declarations": [web_search]}]
    config = {"response_modalities": ["AUDIO"], "tools": tools}
    ```

3.  3

    ## 3. Call the Search API

    The function calls `GET /v1/web-search` with the question in `q`. `num` sets how many results come back. Return only what the model needs to speak, so the reply stays short:

    live\_search.py

    ```python
    import os
    import httpx
    
    specstream = httpx.AsyncClient(
        base_url="https://api.specstream.ai",
        headers={"Authorization": f"Bearer {os.environ['SPECSTREAM_API_KEY']}"},
        timeout=30,
    )
    
    async def search(q: str) -> dict:
        r = await specstream.get("/v1/web-search", params={"q": q, "num": 5})
        r.raise_for_status()
        data = r.json()["data"]
        answer = data.get("answer") or {}
        return {
            "answer": answer.get("value"),
            "answer_page": answer.get("page"),
            "sources": [
                {"title": s.get("title"), "url": s["url"], "snippet": s.get("snippet")}
                for s in data["sources"]
            ],
        }
    ```

4.  4

    ## 4. Answer each tool call

    The Live API does not answer tool calls for you. When a message carries `tool_call`, run the search for each function call and send a `FunctionResponse` with the call's `id` and `name` through `session.send_tool_response`. The model then speaks the answer:

    live\_search.py

    ```python
    import asyncio
    import wave
    from google import genai
    from google.genai import types
    
    client = genai.Client(http_options={"api_version": "v1beta"})
    model = "gemini-3.8-live"
    
    async def main():
        async with client.aio.live.connect(model=model, config=config) as session:
            await session.send_client_content(
                turns={"parts": [{"text": "What did the European Central Bank decide at its last meeting?"}]}
            )
            wf = wave.open("audio.wav", "wb")
            wf.setnchannels(1)
            wf.setsampwidth(2)
            wf.setframerate(24000)  # Output is 24kHz
    
            async for response in session.receive():
                if response.data is not None:
                    wf.writeframes(response.data)
                elif response.tool_call:
                    function_responses = []
                    for fc in response.tool_call.function_calls:
                        try:
                            result = await search(fc.args["q"])
                        except httpx.HTTPError as e:
                            result = {"error": str(e)}
                        function_responses.append(
                            types.FunctionResponse(id=fc.id, name=fc.name, response={"result": result})
                        )
                    await session.send_tool_response(function_responses=function_responses)
    
            wf.close()
    
    asyncio.run(main())
    ```

5.  5

    ## 5. Run it

    Set `GEMINI_API_KEY` and `SPECSTREAM_API_KEY`, run `python live_search.py`, and play `audio.wav`. Print `result` inside the loop to see the pages the answer came from.

## Why a function and not the Google Search tool

The Live API also takes `google_search` as a built in tool. A SpecStream function differs in three ways that matter in a voice app:

-   Your code holds the results. Each call returns the answer, the page it was read from and the ranked results with their URLs, so you can log them, show them on screen next to the voice reply, or drop a site you do not trust.
-   It sits next to your other functions. On Vertex AI, Google's documentation says search tools cannot be combined with function calling in the same setup request. `web_search` is a function, so it goes in the same `function_declarations` list as the rest of your tools.
-   The price is per call, from your balance. Grounding with Google Search on the Live models is 5,000 free search requests a month, shared across Gemini 3 and newer models, then $14 per 1,000 requests, with a cap of 1,500 requests a day. The Search API is $5 per 1,000 searches of up to 10 results, and it is the most accurate web search API on SimpleQA Verified and WideSearch ([scores and method](https://specstream.ai/benchmarks.md)).

## Keep talking while it searches

On `gemini-3.8-live`, the conversation can go on while the search runs. Add `"behavior": "NON_BLOCKING"` to the declaration, and a `scheduling` value to each response: `INTERRUPT` speaks the result at once, `WHEN_IDLE` waits until the model finishes what it is saying, and `SILENT` keeps it for later in the conversation. Run each search in its own task with `asyncio.create_task`, so the loop keeps reading audio while it waits. `gemini-3.1-flash-live-preview` supports synchronous calls only, and `gemini-3.8-live-extended-thinking` supports asynchronous calls only.

## Text from the top pages

Add `"passages": "true"` to `params` when the model needs more than snippets. Each of the first `num` sources then carries an `excerpt`, the text of its page closest to the question, up to about 3,500 characters. The call takes up to about a second more.

## Read a page the caller names

To read a page by its address, declare a second function and answer it with the Extract API. It returns the main text of the page, and of PDF, Word and Excel files:

## Cost

Each `web_search` call is one Search API call at $5 per 1,000 searches of up to 10 results. Each page read with text is $0.80 per 1,000 pages, and a page with no text is not charged. Both come out of your balance with no quote and no approval, and the key's spending limit caps what it can spend. New accounts start with $10 of credit, no card. The [Search API reference](https://specstream.ai/docs/search-api.md) lists every parameter, and [balance and billing](https://specstream.ai/docs/billing.md) has the details.

## Disconnect

Remove the functions from the session config. Then open **Agents & API** in your workspace, choose **API keys**, and revoke the key. Questions go to [support@specstream.ai](mailto:support@specstream.ai).

## More

[SpecStream for Gemini Live API](https://specstream.ai/integrations/gemini-live-api.md) covers what it does in Gemini Live API on one page. Every other tool has its guide in [Connect your tools](https://specstream.ai/docs/integrations.md). You see the most a request can cost before it starts, and the matches are paid from your balance. [Billing](https://specstream.ai/docs/billing.md) has the details. For help, email [support@specstream.ai](mailto:support@specstream.ai).
