Quickstart
Instrument your AI agent in under two minutes. TraceAgently captures every thought, tool call, and error your agent produces and streams them to your dashboard in real time — with no changes to your core agent logic.
1. Install the SDK
# Python
pip install traceagently
# TypeScript / Node
npm install traceagently
2. Get your API key
After signing up, go to your dashboard, open API Keys, and create a new key. The raw key (prefixed ta_live_) is shown exactly once — copy it now.
3. Wrap your agent
from traceagently import TraceAgently
ta = TraceAgently(api_key="ta_live_...")
with ta.trace(agent_id="support-bot", task="Refund user #123") as trace:
trace.thought("I need to check the order database")
trace.tool_call("check_order", {"user_id": 123})
trace.tool_result({"status": "delivered"})
trace.final_response("Cannot refund a delivered order")
That's it. Open your dashboard while the agent runs and watch every event appear live. No polling. No refreshing.
Python SDK
Install from PyPI: pip install traceagently. Requires Python 3.8+. Zero dependencies beyond the standard library.
TraceAgently(api_key)
The top-level client. Create one instance per process — it is thread-safe and reusable.
from traceagently import TraceAgently
ta = TraceAgently(
api_key="ta_live_...", # required
base_url="https://api.traceagently.com", # optional override
timeout=10, # seconds, default 10
)
Constructor parameters
| Parameter | Type | Description |
|---|---|---|
api_key | str | Your ta_live_... API key. Required. |
base_url | str | Override the API base URL. Defaults to https://api.traceagently.com. |
timeout | int | HTTP timeout in seconds. Default 10. |
ta.trace(agent_id, task, **metadata)
Returns a context manager that starts a trace on enter and marks it complete (or failed) on exit. All events recorded inside the with block are attached to this trace.
with ta.trace(
agent_id="billing-agent",
task="Process invoice INV-9912",
# any extra kwargs become trace metadata
model="gpt-4o",
framework="langgraph",
temperature=0.2,
) as trace:
# your agent logic here
pass
# trace is automatically marked "completed" on exit
# raises → trace marked "failed" and exception re-raised
Parameters
| Parameter | Type | Description |
|---|---|---|
agent_id | str | Name of your agent — groups related traces in the dashboard. |
task | str | Human-readable description of what this trace is doing. |
**metadata | any | Arbitrary key/value pairs stored on the trace (model, framework, user ID, etc.). |
trace.thought(content)
Record an internal reasoning step — the agent's "thinking" before it acts.
trace.thought("The user wants a refund. I should check delivery status first.")
trace.tool_call(tool_name, inputs)
Record that the agent is invoking an external tool or function.
trace.tool_call("check_order", {"order_id": "ORD-4521", "user_id": 123})
trace.tool_result(result)
Record the output returned by the tool. Always pair with a preceding tool_call.
trace.tool_result({"status": "delivered", "delivered_at": "2025-03-20T14:22:00Z"})
trace.error(message)
Record an error event. The trace continues — use this for recoverable errors within a run. The context manager will additionally mark the trace failed if an unhandled exception propagates.
try:
result = call_external_api()
except Exception as e:
trace.error(str(e))
# handle gracefully or re-raise
trace.final_response(content)
Record the agent's final output to the end user. This is the last event before the context manager exits.
trace.final_response("Cannot refund a delivered order. Contact support if this is an error.")
Full example
import openai
from traceagently import TraceAgently
ta = TraceAgently(api_key="ta_live_...")
client = openai.OpenAI()
def run_agent(user_request: str):
with ta.trace(agent_id="gpt4o-agent", task=user_request, model="gpt-4o") as trace:
trace.thought("Deciding which tool to use")
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": user_request}]
)
answer = response.choices[0].message.content
trace.final_response(answer)
return answer
TypeScript SDK
Install from npm: npm install traceagently. Works in Node.js 18+ and edge runtimes. Ships with full TypeScript types — no separate @types package needed.
new TraceAgently(options)
import { TraceAgently } from 'traceagently'
const ta = new TraceAgently({
apiKey: 'ta_live_...', // required
baseUrl: 'https://api.traceagently.com', // optional
timeout: 10_000, // ms, default 10 000
})
Options
| Option | Type | Description |
|---|---|---|
apiKey | string | Your ta_live_... API key. Required. |
baseUrl | string | Override the API base URL. |
timeout | number | HTTP timeout in milliseconds. Default 10 000. |
ta.startTrace(options)
Creates a new trace and returns a Trace handle. All subsequent event methods are called on this handle. The trace is marked running until you call trace.end().
const trace = await ta.startTrace({
agentId: 'support-bot',
task: 'Refund user #123',
// any extra fields become trace metadata
model: 'gpt-4o',
framework: 'langchain',
})
Options
| Option | Type | Description |
|---|---|---|
agentId | string | Name of your agent. |
task | string | Human-readable task description. |
[key: string] | any | Any extra fields are stored as trace metadata. |
trace.thought(content)
await trace.thought('Checking order status before deciding on refund')
trace.toolCall(name, inputs)
await trace.toolCall('check_order', { userId: 123, orderId: 'ORD-4521' })
trace.toolResult(result)
await trace.toolResult({ status: 'delivered', deliveredAt: '2025-03-20T14:22:00Z' })
trace.error(message)
await trace.error('External API returned 503 — retrying')
trace.end(finalResponse?)
Closes the trace and marks it completed. Optionally records a final response event before closing.
await trace.end('Cannot refund a delivered order')
// or without a final response:
await trace.end()
Full example
import OpenAI from 'openai'
import { TraceAgently } from 'traceagently'
const ta = new TraceAgently({ apiKey: 'ta_live_...' })
const openai = new OpenAI()
async function runAgent(userRequest: string) {
const trace = await ta.startTrace({
agentId: 'gpt4o-agent',
task: userRequest,
model: 'gpt-4o',
})
try {
await trace.thought('Processing request')
const res = await openai.chat.completions.create({
model: 'gpt-4o',
messages: [{ role: 'user', content: userRequest }],
})
const answer = res.choices[0].message.content ?? ''
await trace.end(answer)
return answer
} catch (err) {
await trace.error(String(err))
await trace.end()
throw err
}
}
REST API Reference
All requests go to https://api.traceagently.com. Every request must include an Authorization header with your API key.
Authentication
Authorization: Bearer ta_live_<your-key>
API keys are different from your dashboard login. Generate them in the dashboard under API Keys. Never share or commit them to version control.
POST /traces
Create a new trace. Returns a traceId you use for all subsequent event calls.
Request body
{
"agentId": "support-bot",
"task": "Refund user #123",
"metadata": {
"model": "gpt-4o",
"framework": "langgraph",
"temperature": 0.2
}
}
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
agentId | string | Yes | Name of your agent — used to group traces in the dashboard. |
task | string | Yes | What this trace is doing. |
metadata | object | No | Arbitrary key/value pairs (model, temperature, user ID, etc.). |
Response — 201 Created
{
"traceId": "trc_01j9z4k8...",
"status": "running",
"startedAt": 1711718400000
}
POST /traces/:traceId/events
Append an event to an existing trace. Events are ordered by timestamp in the dashboard timeline.
Request body
{
"type": "tool_call",
"content": "check_order",
"tokens": 128,
"metadata": { "inputs": { "user_id": 123 } },
"timestamp": 1711718401234
}
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | One of: thought, tool_call, tool_result, error, final_response. |
content | string | Yes | The event payload — text or serialised JSON string. |
tokens | number | No | Token count for this step (used in cost calculator). |
metadata | object | No | Arbitrary extra data. |
timestamp | number | No | Unix ms. Defaults to server receipt time. |
Response — 201 Created
{
"eventId": "evt_0a3x7p...",
"traceId": "trc_01j9z4k8..."
}
GET /traces
List all traces for the authenticated user, newest first. Results are paginated.
Query parameters
| Parameter | Type | Description |
|---|---|---|
agentId | string | Filter by agent ID. |
status | string | running | completed | failed |
limit | number | Results per page. Default 50, max 200. |
cursor | string | Pagination cursor from previous response. |
Response — 200 OK
{
"traces": [
{
"traceId": "trc_01j9z4k8...",
"agentId": "support-bot",
"task": "Refund user #123",
"status": "completed",
"startedAt": 1711718400000,
"endedAt": 1711718409123,
"totalTokens": 842,
"estimatedCostUsd": 0.0024
}
],
"nextCursor": "cur_abc..."
}
GET /traces/:traceId
Fetch a single trace with all its events ordered by timestamp.
Response — 200 OK
{
"traceId": "trc_01j9z4k8...",
"agentId": "support-bot",
"task": "Refund user #123",
"status": "completed",
"events": [
{ "eventId": "evt_001", "type": "thought", "content": "Check order DB", "timestamp": 1711718400100 },
{ "eventId": "evt_002", "type": "tool_call", "content": "check_order", "timestamp": 1711718401200 },
{ "eventId": "evt_003", "type": "tool_result", "content": "{\"status\":\"delivered\"}", "timestamp": 1711718403400 },
{ "eventId": "evt_004", "type": "final_response", "content": "Cannot refund...", "timestamp": 1711718408900 }
]
}
Error codes
| Status | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid Authorization header. |
404 | not_found | Trace ID does not exist or belongs to a different user. |
422 | validation_error | Request body is missing required fields or contains invalid values. |
429 | limit_reached | Monthly trace limit exhausted (Free plan) or trace was killed by a safety rule. Upgrade at traceagently.com/pricing. |
500 | internal_error | Server error. Retry with exponential back-off. |
{
"error": "Monthly limit reached. Upgrade at traceagently.com/pricing",
"code": "limit_reached",
"status": 429
}
Event Types
Every event posted to a trace has a type field. The dashboard uses event types to colour-code the timeline and power error pattern detection.
Internal reasoning — an intermediate thinking step before the agent acts. Map this to chain-of-thought output, scratchpad reasoning, or any "I should..." statement your agent produces. Not shown to end users.
Tool invocation — the agent is about to call a function or external service. The content field should be the tool name; put the input arguments in metadata.inputs.
Tool output — the result returned by a tool. Always pair with a preceding tool_call. Serialise complex objects to JSON before passing as content.
Error or exception — something went wrong. The trace continues after an error event; it is up to you whether to recover or re-raise. Error events are aggregated in the Error Patterns dashboard view.
Final answer — the agent's output to the end user or calling system. Marks the logical end of the agent's work. After this event, close the trace.
Recommended event order
There is no enforced ordering, but the canonical pattern for a ReAct-style agent is:
thought → tool_call → tool_result → thought → tool_call → ... → final_response
Plans & Limits
All limits reset at the start of each billing period. The Free plan resets on the 1st of each month; paid plans reset on the anniversary of your subscription start date.
| Feature | Free | Pro |
|---|---|---|
| Monthly price | $0 | $49 |
| Traces per month | 1,000 | 1,000,000 |
| Events per trace | Unlimited | Unlimited |
| Overage | Hard stop (429) | $0.50 / 1k traces |
| Data retention | 7 days | 90 days |
| Projects (agent IDs) | 1 | Unlimited |
| Kill-switch | 1 rule | Unlimited |
| Loop detection | Yes | Yes |
| Email alerts | — | Yes |
| Trace comparison | — | Yes |
| Magic Fix (AI analysis) | — | Yes |
On the Free plan, once you hit 1,000 traces the API returns 429 for POST /traces for the rest of the month. Events within existing traces are always accepted — only starting new traces is blocked. Upgrade at any time to immediately restore ingestion.
What counts as a trace?
Each call to POST /traces (starting a new agent run) consumes one trace toward your monthly limit. Events within a trace (POST /traces/:traceId/events) are unlimited and do not count against any limit.
Upgrading and downgrading
Upgrades take effect immediately. Downgrades take effect at the end of your current billing period — you keep your higher-tier limits until then. Manage your subscription at any time from the Billing section of the dashboard.