Docs/Guides/Production

Production Best Practices

This guide covers the SDK settings and product features that matter when an instrumented agent goes to production. Examples use the Python SDK (ants-platform).

Configure once from the environment

Create the client once at process startup and call get_client() everywhere else. Keep all settings in environment variables so each deployment can differ without code changes.

python
from ants_platform import AntsPlatform, get_client AntsPlatform() def handle(request): ants = get_client() with ants.start_as_current_observation( name="handle-request", as_type="agent", agent_name="order-agent", input=request ) as agent: result = process(request) agent.update(output=result) return result
VariablePurposeDefault
ANTS_PLATFORM_PUBLIC_KEY, ANTS_PLATFORM_SECRET_KEYProject API key pairnone
ANTS_PLATFORM_HOSTURL of your ANTS Platform appSet it explicitly
ANTS_PLATFORM_TRACING_ENVIRONMENTEnvironment name on every trace, for example production or stagingdefault
ANTS_PLATFORM_RELEASERelease or commit of your applicationnot set
ANTS_PLATFORM_SAMPLE_RATEShare of traces to send, from 0.0 to 1.01.0
ANTS_PLATFORM_FLUSH_ATSpans per batch512
ANTS_PLATFORM_FLUSH_INTERVALSeconds between batch sends5
ANTS_PLATFORM_TIMEOUTTimeout in seconds for SDK API requests5
ANTS_PLATFORM_TRACING_ENABLEDSet to false to stop sending tracestrue
ANTS_PLATFORM_DEBUGVerbose SDK logsfalse

Each variable has a matching constructor argument, such as environment=, release=, sample_rate=, flush_at=, flush_interval=, timeout=, tracing_enabled= and debug=.

Environment names must be lowercase letters, digits, hyphens or underscores and must not start with ants-platform.

ℹ

Use a separate API key pair per service and environment, so you can rotate or revoke one without affecting the others. See API Keys.

Production checklist

Name every agent

The outermost observation of every trace needs an agent_name, or the SDK raises ValueError: agent_name is required. Use a stable name per agent, because the name identifies the agent across traces. Set version= on observations or traces when you ship a new agent version.

Flush on shutdown

The SDK sends data in background batches and flushes automatically when a normal Python process exits. Call flush() yourself where that does not happen, such as at the end of a serverless handler or a scheduled job:

python
from ants_platform import get_client def lambda_handler(event, context): ants = get_client() try: with ants.start_as_current_observation( name="lambda", as_type="agent", agent_name="order-agent", input=event ): return process(event) finally: ants.flush()

In a long-running worker with its own shutdown hook, call get_client().shutdown() there.

Control volume

Set ANTS_PLATFORM_SAMPLE_RATE to send a fraction of traces from high-traffic services. Sampling is per trace, so a sampled trace keeps all its observations.

@observe() captures function arguments and return values by default. For functions with large or sensitive payloads, turn this off per function or globally:

python
from ants_platform import observe @observe(name="score-application", capture_input=False, capture_output=False) def score_application(application): return model.predict(application)

To turn it off for all decorated functions, set ANTS_PLATFORM_OBSERVE_DECORATOR_IO_CAPTURE_ENABLED=false.

Mask sensitive data

A mask function runs on every input, output and metadata value before it leaves your process:

python
from ants_platform import AntsPlatform EMAIL = re.compile(r"[\w.+-]+@[\w-]+\.[\w.]+") def mask(data, **kwargs): if isinstance(data, str): return EMAIL.sub("[email]", data) if isinstance(data, dict): return {key: mask(value) for key, value in data.items()} if isinstance(data, list): return [mask(value) for value in data] return data AntsPlatform(mask=mask)

To detect PII, PCI and PHI in traffic that is already traced, see PII Detection and AI Guardrails. How long trace data is kept is set under Organization Settings > Data Retention, for users with access to it.

Serve prompts with a fallback

If you use Prompt Management, fetch the production label and pass a fallback so a fetch failure never breaks a request. Fetched prompts are cached in the process (60 seconds by default).

python
from ants_platform import get_client from ants_platform.openai import OpenAI ants = get_client() llm = OpenAI() def answer(question): prompt = ants.get_prompt( "support-answer", label="production", fallback="Answer the customer question: {{question}}", cache_ttl_seconds=300, ) with ants.start_as_current_observation( name="answer", as_type="agent", agent_name="support-agent", input=question ): completion = llm.chat.completions.create( name="support-answer", model="gpt-4o-mini", messages=[{"role": "user", "content": prompt.compile(question=question)}], ants_platform_prompt=prompt, ) return completion.choices[0].message.content

Passing ants_platform_prompt=prompt links the generation to the prompt version that produced it.

Verify the deployment

Run get_client().auth_check() once in a deploy smoke test, not in request handlers; it is a blocking network call. Then send one request and confirm the trace appears in Discover AI > Tracing with the expected environment and release.

⚠

The first agent observation in each process looks up the project through the API. If the host is unreachable or the keys are invalid at that moment, opening the observation raises an error in your code. This lookup also runs when tracing is disabled. Check credentials and network access to the host before you send production traffic.

Monitoring in production

QuestionWhere to look
What did a specific request do?Discover AI > Tracing, filtered by environment, user, tags or level
How did a conversation go?Discover AI > Sessions
What are we spending, and on which models?Gauge AI > Cost Dashboard and Cost Performance Metrics
Where is latency coming from?Gauge AI > Latency Dashboard and Latency & Analytics
How is usage trending?Gauge AI > AI Usage
Could a cheaper model do the job?Gauge AI > AI Optimizer (AI Optimizer)
Are answers good?Scores from users, annotators and LLM-as-a-Judge evaluators running on incoming traces

For views specific to your team, build Custom Dashboards from traces, observations and scores. To move trace data into your own systems, use Data Exports or the Public API.

Alerts and spend limits

⚠

Tracing does not send alerts on error rate, latency or cost thresholds. Watch those in the dashboards above, or export the data to your own monitoring system.

What is available today:

  • Automations run when a prompt version is created, updated or deleted, and send a webhook or a Slack message. Use them to notify a channel or trigger a deployment when a prompt label changes. See Automations.
  • Budget AI applies rate limits and USD budgets to LLM traffic routed through it, under Budget AI > Budgets & Limits. A budget either stops requests or only records threshold crossings when it is reached. See Budgets & Limits.
  • Governance surfaces policy violations in Governance > AI Violations and the Risk Dashboard. See AI Governance.

Scaling

Scaling, load balancing and failover are handled by your own deployment platform. The SDK needs nothing special: every instance reads the same environment variables and sends to the same project. Make sure each instance flushes on shutdown so spans are not lost when it is stopped.

Troubleshooting

SymptomLikely cause
Traces missing from serverless functionsNo flush() before the handler returns
ValueError: agent_name is requiredA root observation, @observe() function or OpenAI drop-in call ran outside an agent observation
Fewer traces than requestsANTS_PLATFORM_SAMPLE_RATE is below 1.0
Production and staging traces mixed togetherANTS_PLATFORM_TRACING_ENVIRONMENT not set per deployment
Generations show no costThe model has no price under Settings > Models; see Models & Pricing

For deeper investigation, see Debugging AI Agents.

Next steps

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