Server-Side Integration
The Logic Layer is where Atheon's deep analysis takes place. By integrating on the server, you allow Atheon to generate Intent Fingerprints and power your Knowledge Graph securely, without ever storing raw PIIed data.
1. Install the SDK
pip install atheon-codex
npm install @atheon-inc/codex
2. Initialize
Call init() once at application startup. For all subsequent calls, track(), begin(), and tools/agents, use the global client automatically.
For Django, Flask or other sync frameworks:
import os
import atheon
atheon.init(os.environ["ATHEON_API_KEY"])
For FastAPI, Starlette or other async frameworks:
import os
from contextlib import asynccontextmanager
import atheon
from someasyncframework import Framework
@asynccontextmanager
async def lifespan(app: Framework):
atheon.async_init(os.environ["ATHEON_API_KEY"])
yield
await atheon.async_shutdown()
app = Framework(lifespan=lifespan)
import * as atheon from "@atheon-inc/codex";
// This performs a cryptographic handshake with the Gateway
// and should be awaited before starting your server.
await atheon.init({ apiKey: process.env.ATHEON_API_KEY });
Advanced init options
You can fine-tune the background queue behavior by passing additional parameters:
uploadSize(Node) /upload_size(Python): Events per HTTP batch (default 10).uploadInterval(Node) /upload_interval(Python): Seconds between background flushes (default 1.0).maxQueueSize(Node) /max_queue_size(Python): Max in-memory queue depth (default 10,000).
Python Note: Only one client type per process. Call either
atheon.init()oratheon.async_init(), not both.
3. Track Interactions
Option A — track(): fire-and-forget for complete interactions
Use this when you have the full input and output ready at once.
interaction_id, prompt_hash, fingerprint = atheon.track(
provider="openai",
model_name="gpt-4o",
input=user_query,
output=llm_response,
tokens_input=response.usage.prompt_tokens,
tokens_output=response.usage.completion_tokens,
finish_reason=response.choices.finish_reason,
properties={"agent": "support-bot"},
)
return {
"reply": llm_response,
"interaction_id": str(interaction_id),
"prompt_hash": prompt_hash,
"fingerprint": fingerprint
}
interaction_id, prompt_hash, fingerprint = atheon.async_track(
provider="openai",
model_name="gpt-4o",
input=req.message,
output=final_text,
tokens_input=response.usage.prompt_tokens,
tokens_output=response.usage.completion_tokens,
finish_reason=response.choices.finish_reason,
)
return {
"reply": final_text,
"interaction_id": str(interaction_id),
"prompt_hash": prompt_hash,
"fingerprint": fingerprint
}
const [interactionId, promptHash, fingerprint] = atheon.track({
provider: "openai",
modelName: "gpt-4o",
input: userQuery,
output: llmResponse,
tokensInput: response.usage.prompt_tokens,
tokensOutput: response.usage.completion_tokens,
finishReason: response.choices.finish_reason,
properties: { agent: "support-bot" }
});
return {
reply: llmResponse,
interaction_id: interactionId,
prompt_hash: promptHash,
fingerprint: fingerprint
};
Option B — begin() / finish(): streaming and multi-turn flows
Use this when the interaction spans time — streaming responses, tool calls, or multi-step pipelines. Latency is measured automatically from begin() to finish().
interaction = atheon.begin(
provider="anthropic",
model_name="claude-sonnet-4-5",
input=user_query,
properties={"agent": "rag-pipeline", "environment": "production"},
)
# ... do work, call tools, etc. ...
interaction.set_property("user_tier", "pro")
interaction_id, prompt_hash, fingerprint = interaction.finish(
output=final_text,
tokens_input=80,
tokens_output=220,
finish_reason="stop",
)
interaction = atheon.async_begin(
provider="anthropic",
model_name="claude-sonnet-4-5",
input=user_query,
properties={"agent": "rag-pipeline", "environment": "production"},
)
# ... do work, call tools, etc. ...
interaction.set_property("user_tier", "pro")
interaction_id, prompt_hash, fingerprint = interaction.finish(
output=final_text,
tokens_input=80,
tokens_output=220,
finish_reason="stop",
)
const [interaction, ctx] = atheon.begin({
provider: "anthropic",
modelName: "claude-sonnet-4-5",
input: userQuery,
properties: { agent: "rag-pipeline" }
});
// ... do work, call tools inside contextWith() ...
interaction.setProperty("userTier", "pro");
const [interactionId, promptHash, fingerprint] = interaction.finish({
output: finalText,
tokensInput: 80,
tokensOutput: 220,
finishReason: "stop"
});
4. Track Tools
Wrap any function to record its execution time and errors automatically. The wrapper hooks into the nearest active begin() context.
import atheon
@atheon.tool("vector-search")
def search(query: str) -> list[str]:
return db.search(query)
# Usage — hooks via Python's ContextVar
interaction = atheon.begin(provider="openai", model_name="gpt-4o", input=query)
results = search(query)
interaction.finish(output=results)
import atheon
@atheon.tool("vector-search")
async def search(query: str) -> list[str]:
return await db.search(query)
# Usage — hooks via Python's ContextVar
interaction = atheon.async_begin(provider="openai", model_name="gpt-4o", input=query)
results = await search(query)
interaction.finish(output=results)
import * as atheon from "@atheon-inc/codex";
const search = atheon.tool("vector-search", async (query: string) => {
return db.search(query);
});
// Usage — wrap the execution block in contextWith()
const [interaction, ctx] = atheon.begin({ provider: "openai", modelName: "gpt-4o", input: query });
const results = await atheon.contextWith(ctx, async () => {
return await search(query);
});
interaction.finish({ output: results });
The tool wrapper is a no-op if called outside an active context, thus safe to use unconditionally in your shared logic.
5. Track Sub-Agents
Wrap LLM-backed sub-agent functions to nest their tool calls and token usage inside the root interaction's payload. Everything is shipped in a single event on finish().
import atheon
@atheon.agent("rag-pipeline", provider="anthropic", model_name="claude-haiku-4-5")
def rag_agent(query: str) -> str:
response = llm.messages.create(...)
atheon.set_result(
tokens_input=response.usage.input_tokens,
tokens_output=response.usage.output_tokens,
finish_reason=response.stop_reason,
)
return response.content.text
interaction = atheon.begin(provider="openai", model_name="gpt-4o", input=user_query)
result = rag_agent(user_query)
interaction.finish(output=result)
import atheon
@atheon.agent("rag-pipeline", provider="anthropic", model_name="claude-haiku-4-5")
async def rag_agent(query: str) -> str:
response = await llm.messages.create(...)
atheon.set_result(
tokens_input=response.usage.input_tokens,
tokens_output=response.usage.output_tokens,
finish_reason=response.stop_reason,
)
return response.content.text
interaction = atheon.async_begin(provider="openai", model_name="gpt-4o", input=query)
results = await rag_agent(query)
interaction.finish(output=results)
import * as atheon from "@atheon-inc/codex";
const ragAgent = atheon.agent("rag-pipeline", "anthropic", "claude-haiku-4-5", async (query: string) => {
const response = await llm.messages.create(...);
atheon.setResult({
tokensInput: response.usage.input_tokens,
tokensOutput: response.usage.output_tokens,
finishReason: response.stop_reason
});
return response.content.text;
});
const [interaction, ctx] = atheon.begin({ provider: "openai", modelName: "gpt-4o", input: userQuery });
const result = await atheon.contextWith(ctx, async () => {
return await ragAgent(userQuery);
});
interaction.finish({ output: result });
6. Conversation Grouping
Pass a conversation_id to group multiple turns together in the dashboard.
atheon.track(
provider="openai",
model_name="gpt-4o",
input=turn_1_query,
output=turn_1_response,
conversation_id=conversation_id,
)
atheon.async_track(
provider="openai",
model_name="gpt-4o",
input=turn_1_query,
output=turn_1_response,
conversation_id=conversation_id,
)
atheon.track({
provider: "openai",
modelName: "gpt-4o",
input: turn1Query,
output: turn1Response,
conversationId: conversationId
});
7. Shutdown
Call shutdown() when your process exits to flush any remaining queued events.
atheon.shutdown()
await atheon.async_shutdown()
await atheon.shutdown();