Skip to main content
OpenAI’s tool calling lets a model invoke functions you define. This guide shows how to implement a Ceramic Search function the model can use to retrieve real-time web results when generating a response.

Get your Ceramic API key

Create a free account to get started.

Generating model responses

Ceramic Search works with both the Chat Completions API and the Responses API. Select the one that matches your project.

Set environment variables

export CERAMIC_API_KEY=your_ceramic_api_key
export OPENAI_API_KEY=your_openai_api_key

Install dependencies

pip install openai ceramic_ai

Full example

When the model decides a search is needed, it returns a tool_calls message. You execute the search, return the results, and call the model again to get the final answer.
import os
import json
from openai import OpenAI
from ceramic_ai import Ceramic

openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
ceramic = Ceramic(api_key=os.getenv("CERAMIC_API_KEY"))

TOOL_DESCRIPTION = (
    "Search the web using Ceramic.\n"
    "Use for accurate current information — news, prices, recent events, documentation, general fact checking.\n"
    "Returns up to 10 ranked results with titles, URLs, and descriptions.\n"
    "Ceramic matches exact keywords — it does not interpret natural language or synonyms automatically.\n"
    "Query rules:\n"
    "- Queries must be 2-8 words\n"
    "- Include specific entities, topics, locations, and dates\n"
    "- Do not include uninformative words such as articles (the, a, an). Avoid prepositions (on, about, in, for, of, at, by, with) unless they are within established phrases or names (United States of America, Into the Wild).\n"
    "- Keep word order meaningful (`house cat` and `cat house` return different results)\n"
    "- Good keyword query examples:\n"
    "    - \"2026 Super Bowl halftime performer\"\n"
    "    - \"climate change effects global warming impact\"\n"
    "    - \"beginner investing strategies stocks bonds basics\"\n"
    "If the search returns no useful results, retry with a more specific keyword query."
)

ceramic_search_tool = {
    "type": "function",
    "function": {
        "name": "ceramic_search",
        "description": TOOL_DESCRIPTION,
        "parameters": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "keyword search query with 2–8 words",
                }
            },
            "required": ["query"],
        },
    },
}

messages = [
    {"role": "user", "content": "What are the latest California tenant protection laws?"}
]

# First call — model may decide to search
response = openai.chat.completions.create(
    model="gpt-5.4",
    messages=messages,
    tools=[ceramic_search_tool],
    tool_choice="auto",
)

message = response.choices[0].message

if message.tool_calls:
    messages.append(message)

    for tool_call in message.tool_calls:
        args = json.loads(tool_call.function.arguments)
        results = ceramic.search(query=args["query"])
        messages.append(
            {
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": str(results),
            }
        )

    # Second call — model generates the final answer
    final_response = openai.chat.completions.create(
        model="gpt-5.4",
        messages=messages,
    )
    print(final_response.choices[0].message.content)
else:
    print(message.content)

Run the example

Save the code to a file, then run it from your terminal:
python openai_tool_calling.py

Building agents

In the Agents SDK, wrap Ceramic Search as a function_tool and attach it to your agent. The SDK handles the tool-calling loop automatically.

Set environment variables

export CERAMIC_API_KEY=your_ceramic_api_key
export OPENAI_API_KEY=your_openai_api_key

Install dependencies

pip install openai-agents ceramic_ai

Full example

import os
from agents import Agent, Runner, function_tool
from ceramic_ai import Ceramic

ceramic = Ceramic(api_key=os.getenv("CERAMIC_API_KEY"))

@function_tool
def ceramic_search(query: str) -> str:
    """Search the web using Ceramic.
    Use for accurate current information — news, prices, recent events, documentation, general fact checking.
    Returns up to 10 ranked results with titles, URLs, and descriptions.
    Ceramic matches exact keywords — it does not interpret natural language or synonyms automatically.
    Query rules:
    - Queries must be 2-8 words
    - Include specific entities, topics, locations, and dates
    - Do not include uninformative words such as articles (the, a, an). Avoid prepositions (on, about, in, for, of, at, by, with) unless they are within established phrases or names (United States of America, Into the Wild).
    - Keep word order meaningful (`house cat` and `cat house` return different results)
    - Good keyword query examples:
        - "2026 Super Bowl halftime performer"
        - "climate change effects global warming impact"
        - "beginner investing strategies stocks bonds basics"
    If the search returns no useful results, retry with a more specific keyword query.

    Args:
        query: keyword search query with 2–8 words
    """
    results = ceramic.search(query=query)
    return str(results)

agent = Agent(
    name="Research assistant",
    instructions="You have access to a web search tool. Use it to answer questions with up-to-date information.",
    tools=[ceramic_search],
)

result = Runner.run_sync(agent, "What are the latest California tenant protection laws?")
print(result.final_output)

Run the example

python agents_tool_calling.py