Docs/Guides/Debugging

Debugging AI Agents

Traces are the main debugging tool in ANTS Platform. This guide shows how to make sure traces arrive, how to record failures so you can find them, and how to narrow a problem down to one step. Examples use the Python SDK (ants-platform).

python
from ants_platform import AntsPlatform ants = AntsPlatform( public_key=os.environ["ANTS_PLATFORM_PUBLIC_KEY"], secret_key=os.environ["ANTS_PLATFORM_SECRET_KEY"], host=os.environ["ANTS_PLATFORM_HOST"], )

No traces appear

Work through these checks in order.

Turn on SDK debug logs

python
ants = AntsPlatform(debug=True)

Or set ANTS_PLATFORM_DEBUG=true. Export errors, retries and authentication failures are then logged.

Check credentials and host

python
print(ants.auth_check())

It returns True for valid credentials and raises an error otherwise. The public and secret key must come from the same project, and ANTS_PLATFORM_HOST must be the URL of your ANTS Platform app.

The first agent observation in a process also looks up the project through the API. If the host is unreachable or the keys are wrong, opening that observation raises an error (for example a connection error or Unable to generate agent_id: project_id not available). If either key is missing entirely, the client logs an authentication warning and stays disabled.

Check for the agent_name error

The SDK requires an agent_name on the outermost observation of each trace. If it is missing, opening the observation raises ValueError: agent_name is required for Ants Platform agent tracking. This also happens for @observe() functions and OpenAI drop-in calls made outside any observation. Wrap the work in an agent observation:

python
with ants.start_as_current_observation( name="support-request", as_type="agent", agent_name="support-agent" ): handle_request()

Flush before the process exits

Data is sent in batches in the background. Short scripts, notebooks, jobs and serverless handlers must call ants.flush() before they return.

Check sampling and the kill switch

If sample_rate (or ANTS_PLATFORM_SAMPLE_RATE) is below 1.0, only that share of traces is sent. If tracing_enabled=False (or ANTS_PLATFORM_TRACING_ENABLED=false), or OTEL_SDK_DISABLED=true is set in the environment, nothing is sent.

Record errors so you can find them

An exception raised inside an observation is recorded on that observation and re-raised. For failures you handle yourself, set level and status_message so the step stands out:

python
def retrieve_context(query: str) -> list: with ants.start_as_current_observation( name="retrieve-context", as_type="retriever", input={"query": query} ) as retriever: try: docs = vector_store.search(query) except TimeoutError as error: retriever.update(level="ERROR", status_message=f"search timed out: {error}") return [] if not docs: retriever.update(level="WARNING", status_message="no documents found") retriever.update(output={"count": len(docs)}) return docs

Levels are DEBUG, DEFAULT, WARNING and ERROR. In Discover AI > Tracing, filter by level to list only traces with errors or warnings, then open one and select the highlighted observation to see its input, output and status message. See Traces.

Find the slow step

Give each step its own observation. Every observation records its start and end time, so you do not need to time steps yourself.

python
from ants_platform import observe @observe(name="plan", as_type="generation") def plan(question): return llm_plan(question) @observe(name="search", as_type="tool") def search(plan_text): return run_search(plan_text) def research_agent(question): with ants.start_as_current_observation( name="research-agent", as_type="agent", agent_name="research-agent", input=question ) as agent: result = search(plan(question)) agent.update(output=result) return result

Open the trace and switch to the Timeline view to see which observation took the longest. To compare latency across many requests, use Gauge AI > Latency Dashboard (p95 and p99 by model) and Gauge AI > Latency & Analytics. See Cost & Latency Dashboards.

Log the trace ID and URL from inside an observation, so an error in your application logs leads straight to the trace:

python
logger = logging.getLogger("support") with ants.start_as_current_observation( name="support-request", as_type="agent", agent_name="support-agent" ): trace_id = ants.get_current_trace_id() logger.info("handling request trace_id=%s url=%s", trace_id, ants.get_trace_url()) handle_request()

To group several requests from the same conversation, set a session ID with update_current_trace(session_id=...) and review them together in Discover AI > Sessions. See Sessions.

Add context that helps later

Attach the details you will want when reading a trace weeks later:

python
with ants.start_as_current_observation( name="support-request", as_type="agent", agent_name="support-agent", input=question ): ants.update_current_trace( user_id=user_id, session_id=ticket_id, version="2026.10.1", tags=["support", "chat"], metadata={"channel": "chat", "priority": "high"}, ) handle_request()

You can filter traces by user, session, tags, level and environment in Tracing.

Mark bad outputs and keep them as test cases

When you find a bad answer, score it so it shows up in score filters and dashboards:

python
ants.create_score( name="correct", value=0, trace_id="<trace-id>", data_type="BOOLEAN", comment="Quoted the wrong exchange rate", )

Then save the failing input to a dataset so you can rerun it after a fix:

python
ants.create_dataset(name="currency-regressions") ants.create_dataset_item( dataset_name="currency-regressions", input={"question": "How much is 100 USD in EUR?"}, expected_output={"answer": "92.0 EUR"}, source_trace_id="<trace-id>", )

See Scores, Datasets and Experiments. To grade outputs automatically, set up LLM-as-a-Judge.

Debug framework integrations

LangChain. Pass the handler on every call and name the agent in metadata:

python
from ants_platform.langchain import CallbackHandler handler = CallbackHandler() chain.invoke( {"question": question}, config={ "callbacks": [handler], "metadata": { "ants_platform_agent_name": "support-agent", "ants_platform_session_id": ticket_id, }, }, )

Each chain step, LLM call and tool call becomes a nested observation. See LangChain.

CrewAI. Create one EventListener() after the client and before crew.kickoff(). See CrewAI troubleshooting.

OpenTelemetry. If spans sent to /api/public/otel/v1/traces do not appear, check the Authorization: Basic header and the endpoint path. See Sending Data In.

Quick reference

ProblemWhere to look
Agent hangs or is slowTrace Timeline view; Gauge AI > Latency Dashboard
Errors in productionDiscover AI > Tracing, filtered by level ERROR
Wrong answersTrace input and output; scores; LLM-as-a-Judge
Costs higher than expectedGauge AI > Cost Dashboard; AI Optimizer
One user's problemDiscover AI > Users, or filter Tracing by user

Next steps

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