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
- Chat Completions API
- Responses API
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)
Maintain a running
input_list starting with the user message. After the first call, append all output items to the list. When you find a function_call item, execute the search and append a function_call_output before calling the API again for 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."
)
TOOLS = [
{
"type": "function",
"name": "ceramic_search",
"description": TOOL_DESCRIPTION,
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "keyword search query with 2–8 words",
}
},
"required": ["query"],
},
}
]
user_input = "What are the latest California tenant protection laws?"
input_list = [{"role": "user", "content": user_input}]
while True:
response = openai.responses.create(
model="gpt-5.4",
input=input_list,
tools=TOOLS,
)
input_list += response.output
tool_calls = [item for item in response.output if item.type == "function_call"]
if not tool_calls:
print(response.output_text)
break
for item in tool_calls:
if item.name == "ceramic_search":
query = json.loads(item.arguments)["query"]
results = ceramic.search(query=query)
input_list.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": str(results),
})
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 afunction_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

