Docs/Core Concepts/Tracing

Tracing Fundamentals

A trace records one end-to-end run of your application. Inside it, observations record each step: spans for work, generations for LLM calls and events for points in time. This page shows how to create them with the SDKs. Install and configure an SDK first (see Installation).

Both SDKs are built on OpenTelemetry. Every observation is an OpenTelemetry span, so spans from other OpenTelemetry libraries in your process nest into the same trace.

Creating a trace

The first observation you start becomes the root of a new trace. Observations started inside it become its children.

python
from ants_platform import AntsPlatform ants = AntsPlatform() # reads ANTS_PLATFORM_PUBLIC_KEY, _SECRET_KEY, _HOST def handle(query: str) -> str: with ants.start_as_current_span( name="support-request", agent_name="support_agent", input={"query": query}, ) as root: with ants.start_as_current_span(name="retrieve-docs") as retrieval: docs = ["doc-1", "doc-2"] retrieval.update(output=docs) with ants.start_as_current_observation( name="answer", as_type="generation", model="gpt-4o", input=[{"role": "user", "content": query}], ) as generation: answer = "You can track your order from the Orders page." generation.update( output=answer, usage_details={"input": 120, "output": 45}, ) root.update(output={"answer": answer}) return answer handle("Where is my order?") ants.flush()
⚠

The Python SDK requires agent_name on the root observation of every trace. Without it, the SDK raises ValueError: agent_name is required. Child observations inherit the agent from their parent.

Decorators and wrappers

Trace whole functions without context managers:

python
from ants_platform import observe @observe() def retrieve(query: str) -> list[str]: return ["doc-1", "doc-2"] @observe(as_type="generation") def call_llm(prompt: str) -> str: return "..." with ants.start_as_current_span(name="support-request", agent_name="support_agent"): call_llm(str(retrieve("Where is my order?")))

@observe captures the function's arguments and return value. Turn this off with capture_input=False and capture_output=False, or globally with ANTS_PLATFORM_OBSERVE_DECORATOR_IO_CAPTURE_ENABLED=false. A decorated function must run inside an observation that has an agent_name.

Observation types

The SDKs accept span, generation, event, agent, tool, chain, retriever, evaluator, guardrail and embedding. ANTS Platform stores three types: span, generation and event. generation and embedding are stored as generations, event as an event, and the rest as spans. Give observations clear names so you can tell steps apart.

Sessions and users

Set trace-level attributes from anywhere inside the trace:

python
ants.update_current_trace( user_id="user-123", session_id="conversation-42", tags=["support", "web"], metadata={"plan": "pro"}, version="1.4.0", )
  • Session ID groups traces into a session, for example every turn of one conversation.
  • User ID attributes the trace to an end user on the Users page.
  • Tags are short labels for filtering. Metadata is a JSON object for any other context.
  • Environment is set on the client (environment= in Python) or with ANTS_PLATFORM_TRACING_ENVIRONMENT. Use lowercase names.
  • Release is set with release= or ANTS_PLATFORM_RELEASE.

With OpenTelemetry, use the user.id and session.id span attributes. See OpenTelemetry.

Tokens and cost

Record token counts on generations with usage_details (Python) or usageDetails (JS/TS), using keys such as input and output. If you do not send a cost, ANTS Platform calculates it from the model name and your model definitions. To send your own cost, use cost_details / costDetails.

The OpenAI and LangChain integrations record model, tokens and timing for you:

python
from ants_platform.openai import openai # instead of: import openai

See Python SDK, JS/TS SDK and LangChain & LangGraph.

Errors

Mark failed steps with a level and a status message:

python
with ants.start_as_current_span(name="call-tool") as span: try: run_tool() except Exception as error: span.update(level="ERROR", status_message=str(error)) raise

Levels are DEBUG, DEFAULT, WARNING and ERROR. The trace table shows counts per level, and you can filter on them. In JS/TS, pass { level: "ERROR", statusMessage } to update().

Distributed tracing

To continue a trace in another service, pass the trace ID and parent observation ID along with the request.

  • Python: ants.get_current_trace_id() and ants.get_current_observation_id() in the caller; start_as_current_span(..., trace_context={"trace_id": ..., "parent_span_id": ...}) in the callee.
  • JS/TS: getActiveTraceId() and getActiveSpanId() in the caller; parentSpanContext in the options of startObservation in the callee.
  • OpenTelemetry: standard W3C traceparent propagation works, because the SDKs use OpenTelemetry context.

Use create_trace_id(seed=...) (Python) or createTraceId(seed) (JS/TS) to derive a trace ID from your own request ID.

Sampling

Sampling is set in the SDK and applies per trace, so a sampled trace is always complete.

python
ants = AntsPlatform(sample_rate=0.2) # or ANTS_PLATFORM_SAMPLE_RATE=0.2

Unsampled traces are never sent and use no credits.

Flushing

The SDKs send data in the background in batches. In short-lived processes (scripts, serverless functions, CLI tools), flush before exit:

  • Python: ants.flush(), or ants.shutdown() at the end of the process.
  • JS/TS: await provider.forceFlush() or await provider.shutdown().

Masking sensitive data

Both SDKs accept a mask function that runs on input, output and metadata before data leaves your process. See Data Privacy.

Best practices

  • Name steps by what they do (retrieve-docs, classify-intent), not by implementation details.
  • Use a stable agent name per application. It identifies the agent across releases. Change the display name, not the agent name.
  • Always set session and user IDs in chat applications.
  • Record tokens on every generation so cost is accurate.
  • Use lowercase environment names, such as production and staging.
  • Flush in short-lived processes.

Next steps

© 2026 ANTS Platform, Inc.Docs v1.0 · Last updated June 2026