Talqing Python SDK
The Python client for the Talqing /v1 API, generated from openapi/openapi.json.
It is the same set of operations, under the same names, as the TypeScript SDK —
both are generated from the surface backend/api/sdk_surface.py declares.
httpx is the only runtime dependency. Responses come back as decoded JSON,
described by TypedDicts: nothing is validated, coerced or renamed on arrival.
Install
pip install talqing
Python 3.10 or newer. The package ships a py.typed marker, so a type checker
in your project sees every TypedDict it declares.
To work against a checkout instead: uv pip install -e clients/python.
Authentication
Create a personal access token on the dashboard's Tokens page. The client sends
it as Authorization: Bearer <token>.
from talqing import Talqing
with Talqing(token="tq_...", base_url="https://api.in.talqing.com") as talqing:
print(talqing.auth.me())
Talqing.from_env() reads the same two values from TALQING_API_KEY and
TALQING_BASE_URL:
export TALQING_API_KEY="your-personal-access-token"
export TALQING_BASE_URL="http://localhost:8000"
with Talqing.from_env() as talqing:
print(talqing.auth.me())
base_url has no default. A client that quietly points at localhost fails in
production as a connection error three layers down; one that refuses to start
says what is actually wrong.
The shape of it
Operations are reached by resource, exactly as the API names them:
talqing.agents.list(limit=50)
talqing.agents.get(agent_id)
talqing.agents.versions.rollback(agent_id, 3)
talqing.calls.batches.pause(batch_id)
talqing.telephony.phone_numbers.assign(number_id, agent_id=agent_id)
Path parameters are positional; everything else — request body fields and query parameters alike — is a keyword argument:
agent = talqing.agents.create(
config={"name": "Support bot", "channel": "text", "prompt": "Be concise."}
)
talqing.agents.update(agent["id"], config={**agent["config"], "greeting": None})
talqing.agents.publish(agent["id"])
An argument you do not pass is not sent. That is what makes a PATCH able to
say null:
talqing.orgs.update(retention_days=None) # keep call content forever
talqing.orgs.update(name="Acme") # leave the retention policy alone
The one name that is not the API's own is telephony.phone_numbers.import_() —
import is a Python keyword.
Errors
Every non-2xx raises TalqingAPIError. There is one error shape, so there is
nothing to branch on:
from talqing import TalqingAPIError
try:
talqing.agents.publish(agent_id)
except TalqingAPIError as error:
print(error.status_code, error) # 400 config is invalid
for problem in error.errors: # ['llm: unknown model gpt-4.9']
print(problem)
Pagination
Every list endpoint pages the same way, so one helper covers all of them. Anything else the endpoint filters on passes straight through:
from talqing import paginate
for agent in paginate(talqing.agents.list):
print(agent["config"]["name"])
for call in paginate(talqing.calls.list, agent_id=agent_id, type="SIP_INBOUND"):
print(call["id"], call["cost"])
Live streams
Six endpoints stay open and push events. Each frame is decoded and repeats its
own name in event, which is what tells the frames apart:
for event in talqing.conversations.events(conversation_id):
if event["event"] == "assistant.delta":
print(event["text"], end="", flush=True)
Use it as a context manager when the loop may exit early, so the connection closes with it:
with talqing.knowledge.events(kb_id) as events:
for event in events:
if event["event"] == "status":
print("build finished:", event["status"])
break
Text conversations
Text agents do not use LiveKit rooms. Open the conversation, then send turns —
both addressed by your own contact_key, so the same key always reaches the same
thread — and watch it happen on the stream above:
conversation = talqing.conversations.create(contact_key="user-42", agent_id=agent_id)
talqing.conversations.messages.create(
contact_key="user-42", message="Hello", client_message_id=str(uuid4())
)
A message returns as soon as it is accepted, carrying the user's own item. The
agent's reply arrives on the event stream, or from
talqing.conversations.items.list(conversation["id"]).
Voice and video agents take a LiveKit room token instead:
token = talqing.calls.token(agent_id=agent_id)
print(token["server_url"], token["participant_token"])
Async
AsyncTalqing has the same surface with every operation a coroutine. A stream
is the exception: it is not awaited on either client, so async for reads the
way for does.
import asyncio
from talqing import AsyncTalqing, paginate_async
async def main() -> None:
async with AsyncTalqing.from_env() as talqing:
await talqing.agents.list()
async for agent in paginate_async(talqing.agents.list):
print(agent["id"])
async for event in talqing.copilot.agents.stream(agent_id):
print(event["event"])
asyncio.run(main())
Types
Every request and response shape is exported from talqing, named as the API
names it:
from talqing import AgentConfig, AgentResponse, CallOutcome, OperationRequest
A response is a plain dict at runtime — the TypedDicts describe it for your
type checker and your editor, and cost nothing when you run. That also means the
SDK can never reject a payload the API considers valid.
Page[T] is the shape every list endpoint returns:
page = talqing.tools.list(limit=50)
page["items"], page["has_more"], page["limit"], page["offset"]
Escape hatches
talqing.request(...) calls a path directly with this client's credentials and
error handling, for an endpoint that shipped since this SDK was generated.
talqing.http is the underlying httpx.Client, already carrying the base URL
and the token, for anything else.
talqing.google_login_url() and talqing.oauth_start_url(provider) build the
two browser redirects, which are not operations and so cannot be generated.
Regenerating
src/talqing/gen is generated and checked in. After re-running
openapi/export.py:
python clients/python/generate.py # rewrite it
python clients/python/generate.py --check # or just assert it is current
Everything else in src/talqing is hand-written: the client, the transport, the
error, and the pagination helper — what the document cannot say.
cd clients/python && pytest && mypy
Metadata
Release files for talqing 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| talqing-0.1.0.tar.gz | 116.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| talqing-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 221.2 kB
Release files / talqing-0.1.0.tar.gz
| Download URL | talqing-0.1.0.tar.gz |
|---|---|
| Size | 116.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
263bfa561e30abb02c4cdeb9391176b4a374a35967e0c810297b79b788d980bd
|
|
BLAKE2b-256 checksum How to use checksums |
e14dfa5c04f395000ecae548aa94279d02fbd9e2d1085013d3280837ba88e5e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|
Release files / talqing-0.1.0-py3-none-any.whl
| Download URL | talqing-0.1.0-py3-none-any.whl |
|---|---|
| Size | 105.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
90cba0dde3dc2e1b30f394d7f18bae752e31bfcb22c2e8cdc5d1f75e2e4152ec
|
|
BLAKE2b-256 checksum How to use checksums |
570c81395a4a594d680be6ac23a4ef9c476410476c08fb395dc9aabce1dacfff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.13
|