Chatsee SDK (Python)
Instrument an LLM agent so every turn arrives at ChatSee as a trace: what the user asked, what the agent answered, which tools ran, how long each one took, what failed, and who it was for.
pip install chatsee-ai
Quick start
from chatsee import ChatseeTracker
tracker = ChatseeTracker(
agent_id="agent_1",
tenant_id="tenant_1",
api_base_url="dev", # environment alias, or a full URL
user_id="u_123", # optional: who the end user is
)
tracker.start_turn("Where is my order?")
with tracker.track_tool_call("lookup_order", {"id": "A-91"}) as call:
call["result"] = lookup_order("A-91")
tracker.end_turn("It ships tomorrow.")
One start_turn … end_turn pair is one turn. Everything logged in between —
tool calls, exceptions, metadata — belongs to that turn and is sent in a single
request when it closes.
What gets captured
| Captured | How |
|---|---|
| User and bot message | start_turn / end_turn |
| End user identity | user_id (see below) |
| Session grouping | session_id, or the API generates one |
| Tool calls: name, arguments, result, error | track_tool_call / log_tool_call |
| Per-tool duration | measured automatically by track_tool_call |
| Turn duration | measured between start_turn and end_turn |
| Token usage and cost | log_model_call (see below) |
| Errors | log_exception, or any exception raised inside track_tool_call |
| System prompt | start_turn(system_prompt=...) |
| Anything else | start_turn(metadata={...}) |
Durations are milliseconds of wall clock. When a duration was not measured it is
sent as absent, never as 0 — downstream latency figures are built from real
measurements only, so an unmeasured call is excluded rather than counted as
instant.
Timing tool calls
track_tool_call is the recommended form: it times the call, records the
result, and still logs the call if the tool raises before re-raising to you.
with tracker.track_tool_call("search", {"q": q}) as call:
call["result"] = search(q) # exceptions here are logged, then re-raised
If you already have the timing, or the call happened elsewhere, log it directly:
tracker.log_tool_call("search", {"q": q}, result=hits, duration_ms=412)
tracker.log_tool_call("refund", {"id": "A-91"}, error="gateway timeout")
Both feed the per-tool metrics the ChatSee front end reads — call counts, error rate, and p50/p95 latency per tool.
Recording token usage
The SDK never sees your model calls, so it cannot count tokens for you — hand it the usage object the provider already returned, once per call:
resp = client.chat.completions.create(model="gpt-4o", messages=msgs)
tracker.log_model_call(model="gpt-4o", provider="openai", usage=resp.usage)
The field names are mapped for you, so the object goes in as it comes out:
resp.usage for OpenAI and Anthropic, resp.usage_metadata for Gemini. Pass the
numbers directly instead if you already have them:
tracker.log_model_call(model="gpt-4o", prompt_tokens=1180, completion_tokens=240)
Log every call the turn made — a retry, a router call, a summarizer — and ChatSee
reports the turn's total from the sum. It also reports how many of those calls
reported usage at all, which is what stops an unmeasured turn being read as a
cheap one: a turn where nothing reported is shown as unavailable, not as zero
tokens. cost_usd is accepted but never inferred; omit it unless the provider
priced the call.
Identifying the end user
user_id is a first-class field, so traces can be filtered and grouped by
person rather than by conversation. It is optional — when nothing is supplied,
ingestion assigns a deterministic anonymous id per session — but a real id is
what lets you follow one user across sessions.
tracker = ChatseeTracker(..., user_id="u_123") # one tracker, one user
tracker.start_turn("Hello", user_id="u_456") # one tracker, many users
Precedence: start_turn(user_id=...), then the tracker-level user_id, then
metadata["user_id"] — the older metadata form keeps working as a fallback.
Environments
Select an environment by passing an alias as api_base_url, or any full URL.
| Alias | URL |
|---|---|
dev |
https://dev-react.chatsee.ai/api |
dev-legacy |
https://dev.chatsee.ai/api |
qa |
https://qa.chatsee.ai/api |
demo |
https://gcp-demo.chatsee.ai/api |
prod (default) |
https://app.chatsee.ai/api |
poc |
https://app.chatsee.ai/api |
Redaction classifiers are fetched from the same environment
(…/v1/redaction/fetch-classifiers); override with redaction_classifiers_url.
Closing a conversation early
Conversations are normally flushed by an inactivity timer. If you know a turn is the last one, say so and it flushes immediately:
tracker.end_turn("Glad I could help.", is_final_turn=True)
Batching
Send many turns as one API call — one Processor run instead of one per turn. Useful for backfills and imports.
tracker.send_batch([
{"user_message": "hi", "bot_message": "hello", "session_id": "s1"},
{"user_message": "thanks", "bot_message": "any time", "session_id": "s1"},
])
Redaction
Redaction runs client-side, before anything leaves the process. Classifiers come from your environment and are cached.
tracker = ChatseeTracker(..., redaction_enabled=True) # redacts each turn
Or redact a payload on its own, without a tracker:
from chatsee import redact
redact({"message": "Card 4111 1111 1111 1111"}, api_base_url="qa", fields_to_redact="*")
Defaults to user_message, bot_message and interactions; set
redaction_fields_to_redact (or fields_to_redact="*") to change that.
Closed-loop remediations
Pull remediation skills for this agent and acknowledge the ones you have
injected into its system prompt. Requires mcp_server_url and mcp_api_key;
tenant and agent are resolved server-side from the key.
tracker = ChatseeTracker(..., mcp_server_url="https://…", mcp_api_key="…")
pending = tracker.fetch_remediations() # or mode="all"
tracker.acknowledge_remediations([r["id"] for r in pending["remediations"]])
Track Claude Code (adapter)
Claude Code is a closed CLI, so rather than instrumenting it the adapter reads its session logs, reconstructs each turn and sends it through the SDK.
# preview (sends nothing)
python -m chatsee.adapters.claude_code --latest --dry-run
# one-time hook install -> every completed turn auto-streams, no terminal needed
python -m chatsee.adapters.claude_code --install-hook \
--agent-id <AGENT_ID> --tenant-id <TENANT_ID> --env dev
# remove it
python -m chatsee.adapters.claude_code --uninstall-hook
Alternatives to the hook: --watch (foreground tail) or a one-shot run. A
per-session checkpoint (~/.chatsee/claude_code_state.json) prevents duplicates.
Redaction is on by default here. Claude Code turns — tool arguments and
results especially — often contain secrets and PII, so the adapter redacts
client-side before sending (user_message, bot_message,
tool_calls_details, exception, system_prompt). Change the set with
--redact-fields a,b,c, or disable with --no-redact (not recommended). The
setting is preserved in installed hooks.
Notes
agent_idandtenant_idare required; there is no API key on the tracking path.verify_ssldefaults toFalsefor the internal environments; setTruefor public ones.- Encryption support has been removed from this SDK.
Release files for chatsee-ai 0.14.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 | |
|---|---|---|---|
| chatsee_ai-0.14.0.tar.gz | 37.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| chatsee_ai-0.14.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 69.1 kB
Release files / chatsee_ai-0.14.0.tar.gz
| Download URL | chatsee_ai-0.14.0.tar.gz |
|---|---|
| Size | 37.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3f2d5839773461cc037e83b0dff479c9a23a64ca722907d25a05ec98dbb90fe6
|
|
BLAKE2b-256 checksum How to use checksums |
5fbee4b9baa7a158e0a0d0f86d1700c2aade05c0bcaaccaf0498a1ac9ac0846e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / chatsee_ai-0.14.0-py3-none-any.whl
| Download URL | chatsee_ai-0.14.0-py3-none-any.whl |
|---|---|
| Size | 31.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ef3e97840e32c0982a013c8b6ce15863c55d7e17c47fdc704906cd9829585b07
|
|
BLAKE2b-256 checksum How to use checksums |
e52c57e8808f3fef473e9ea905daacd2e974a7afa883a6aa6aead1b29c5c546c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|