Skip to main content

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_id and tenant_id are required; there is no API key on the tracking path.
  • verify_ssl defaults to False for the internal environments; set True for public ones.
  • Encryption support has been removed from this SDK.

Release files for chatsee-ai 0.13.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for chatsee-ai 0.13.1
File Size Uploaded
chatsee_ai-0.13.1.tar.gz 37.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for chatsee-ai 0.13.1
File Interpreter ABI Platform
chatsee_ai-0.13.1-py3-none-any.whl Python 3 none any Details

Total release size: 68.5 kB

Release files / chatsee_ai-0.13.1.tar.gz

Download URL chatsee_ai-0.13.1.tar.gz
Size 37.1 kB
Tags Source
SHA-256 checksum
How to use checksums
8311df8a9c045b95a2474a8361098e107f838b350f69fc030138fb39ac5cbea0
BLAKE2b-256 checksum
How to use checksums
df1c05b5a8e313c1540a7ca7e34c811bae680b3d06c3ac7818a4eebda2d89d5d
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.13.1-py3-none-any.whl

Download URL chatsee_ai-0.13.1-py3-none-any.whl
Size 31.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3fe4ce9f85043e2a25081c020851ec89bbc88bb9cb9d9cecce8c5e17c9a49561
BLAKE2b-256 checksum
How to use checksums
6e524c50100919245661afc70c5a7c7c83da6fb380e1da8ccb3f64723406c310
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

0.14.0

2 release files

This release

0.13.1 This release

2 release files

0.13.0

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.3

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page