import os
import anthropic
from ceramic_ai import Ceramic
claude = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_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 = {
"name": "ceramic_search",
"description": TOOL_DESCRIPTION,
"input_schema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "keyword search query with 2–8 words",
}
},
"required": ["query"],
},
}
SYSTEM = "You have access to a web search tool. Use it to answer questions with up-to-date information."
messages = [{"role": "user", "content": "What are the latest California tenant protection laws?"}]
response = claude.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
system=SYSTEM,
messages=messages,
tools=[ceramic_search_tool],
)
while response.stop_reason == "tool_use":
tool_use_blocks = [block for block in response.content if block.type == "tool_use"]
# Append the full assistant message
messages.append({"role": "assistant", "content": response.content})
# Execute each tool call and collect results
tool_results = []
for tool_use in tool_use_blocks:
if tool_use.name == "ceramic_search":
results = ceramic.search(query=tool_use.input["query"])
tool_results.append({
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": str(results),
})
messages.append({"role": "user", "content": tool_results})
response = claude.messages.create(
model="claude-opus-4-6",
max_tokens=1024,
system=SYSTEM,
messages=messages,
tools=[ceramic_search_tool],
)
print(next((block.text for block in response.content if block.type == "text"), ""))