SDKs and frameworks
OpenAI
Wrap an OpenAI client, and the model gets a telem_search tool, with
query lineage on every search. The wrap also records
the conversation for you.
Using a coding agent? Find the one you use on Integrations.
Telem.wrap(client) patches an OpenAI client in place and returns the same object.
Its chat.completions.create then has Telem search. For openai.AsyncOpenAI, use
AsyncTelem.wrap(client). One wrapped client is one agent conversation.
Install
Section titled “Install”pip install "telem-sdk[openai]"openai is an optional extra. The wrap module is duck-typed. It imports the real
package only to give a clearer error when the object you pass in is not shaped like an
OpenAI client.
Authentication
Section titled “Authentication”Create an API key under API keys in the Telem console.
The guided installer writes it to ~/.telem/credentials.json, which the client
reads. You can also set it as TELEM_API_KEY, or pass it in code. See
API keys for the full rules.
from openai import OpenAIfrom telem import Telem
telem = Telem() # environment, then ~/.telem/credentials.jsonclient = OpenAI() # reads OPENAI_API_KEY from the environmenttelem.wrap(client) # patches client.chat.completions.create in place
completion = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "What's new in the Telem search API?"}],)print(completion.choices[0].message.content)print(completion.telem_responses) # list[SearchResponse] telem ran answering this turnprint(client.telem_messages) # the recorded conversation so farAfter each call, client.telem_messages holds every request and reply of the
conversation.
The model gets one tool, telem_search. It sets the query and, when the task needs
it, a date window. The wrap gives
the model no tool to read a page. Your own code can still read pages with
telem.fetch(): see the Fetch tab on Python SDK.
wrap() also takes options for every search the model makes:
| Option | What it sets |
|---|---|
tier |
The search tier. |
providers_include |
Only these providers. |
num_results |
Results per provider. The server default is 5. |
goal |
What the conversation is for, in a few words. Telem stores it with each search. |
context |
Why the searches are made, in a sentence or two. Telem stores it with each search. |
result_max_len |
The most characters of each result that the model reads. The default is 2,048. |
An option you leave out falls back to the Telem client’s default, such as
Telem(default_providers_exclude=[...]). See Python SDK.
The model cannot change goal or context for one search: the wrap sends the same
text with every search of the conversation.
The async version has the same shape. Use AsyncTelem and openai.AsyncOpenAI:
import asynciofrom openai import AsyncOpenAIfrom telem import AsyncTelem
async def main(): telem = AsyncTelem() client = AsyncOpenAI() telem.wrap(client) completion = await client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "What's new in the Telem search API?"}], ) print(completion.choices[0].message.content)
asyncio.run(main())Both examples need a real OPENAI_API_KEY, and both make a live model call.
Subagents
Section titled “Subagents”Give a subagent its own wrapped client, and pass the parent’s client as parent. The
subagent’s searches then appear in the console under the agent that started it:
child = OpenAI()telem.wrap(child, parent=client) # when you delegate, not at startupThe wrap records the parent’s conversation at wrap() time. So wrap the child when you
delegate to it. If you wrap it at startup, the record is older than anything the
parent said.
Conversation identity
Section titled “Conversation identity”One wrapped client is one conversation, and the wrap makes its own conversation id. If one conversation spans several wrapped clients, such as a web server that wraps a new client for each request, pass the same id each time:
telem.wrap(client, conversation_id=chat.id)Without it, each request appears in the console as a separate conversation.
- The context window starts at the first message. When you trim or summarize the
history, a new window starts by itself. To name the window yourself, pass
context_window_id. - After a search,
client.telem_session_idholds the session id, fortelem.sessions.
Streaming isn’t supported yet
Section titled “Streaming isn’t supported yet”A stream=True call bypasses Telem completely. It gets no telem_search tool, no
query lineage and no reply recording. The wrap emits a UserWarning each time this
happens.
Next steps
Section titled “Next steps”- Python SDK: the client options, search options and errors
- LangChain: the same search tool for LangChain and LangGraph agents
- Search parameters: choose providers, tiers and date windows