Documentation
Custom Agent Integration
Track any AI agent with Guardy, not just LangChain. Manual instrumentation gives you full control over what gets tracked.
When to Use Manual Tracking
Building with a custom agent framework, not LangChain.
Using the OpenAI or Anthropic SDKs directly.
Only want to track certain events, not everything.
Using JavaScript/TypeScript or another language.
Basic Pattern
The simple begin/finish pattern works for most use cases:
import guardy
guardy.configure(api_key="guardy_live_xxx")
def handle_request(user_input: str, user_id: str):
# Begin tracking
interaction = guardy.begin(
user_id=user_id,
event="chat_request",
input=user_input
)
try:
# Your agent logic
response = your_agent.run(user_input)
# Finish with success
interaction.finish(
output=response,
success=True,
estimated_cost=0.023
)
return response
except Exception as e:
# Finish with failure
interaction.finish(
success=False,
failure_reason=str(e)
)
raiseFull Control Pattern
For more granular tracking, use the GuardyClient directly:
from guardy import GuardyClient
import openai
client = GuardyClient(api_key="guardy_live_xxx")
def handle_request(user_input: str, user_id: str):
# Create session
session_id = client.create_session(
name=f"Request: {user_input[:40]}...",
agent_name="my-custom-agent",
user_id=user_id,
metadata={"source": "api"}
)
try:
# Track decision
client.track_decision(
session_id=session_id,
reasoning="User asked a question, will search then respond",
alternatives=["direct_response", "clarify_question"]
)
# Track tool call
search_results = search_database(user_input)
client.track_tool_call(
session_id=session_id,
tool_name="search_database",
tool_input={"query": user_input},
tool_output={"results": search_results},
reasoning="Searching for relevant information"
)
# Make LLM call
completion = openai.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": user_input}
]
)
response = completion.choices[0].message.content
usage = completion.usage
# Complete session
client.complete_session(
session_id=session_id,
success=True,
estimated_cost=calculate_cost(usage),
prompt_tokens=usage.prompt_tokens,
completion_tokens=usage.completion_tokens
)
return response
except Exception as e:
client.complete_session(
session_id=session_id,
success=False,
failure_reason=str(e)
)
raiseTracking Tool Calls
Wrap your tool functions to automatically track them:
def tracked_tool(client, session_id):
"""Decorator to track tool calls."""
def decorator(func):
def wrapper(*args, **kwargs):
tool_input = {"args": args, "kwargs": kwargs}
try:
result = func(*args, **kwargs)
client.track_tool_call(
session_id=session_id,
tool_name=func.__name__,
tool_input=tool_input,
tool_output={"result": result}
)
return result
except Exception as e:
client.track_tool_call(
session_id=session_id,
tool_name=func.__name__,
tool_input=tool_input,
tool_output={"error": str(e)}
)
raise
return wrapper
return decorator
# Usage
@tracked_tool(client, session_id)
def search_database(query: str):
return database.search(query)
@tracked_tool(client, session_id)
def send_email(to: str, subject: str, body: str):
return email_service.send(to, subject, body)TypeScript Example
import { GuardyClient } from '@guardy/sdk';
import OpenAI from 'openai';
const guardy = new GuardyClient({
apiKey: process.env.GUARDY_API_KEY!
});
const openai = new OpenAI();
async function handleRequest(userInput: string, userId: string) {
const sessionId = await guardy.createSession({
name: `Request: ${userInput.slice(0, 40)}...`,
agentName: "my-custom-agent",
userId
});
try {
// Track tool call
const searchResults = await searchDatabase(userInput);
await guardy.trackToolCall({
sessionId,
toolName: "search_database",
toolInput: { query: userInput },
toolOutput: { results: searchResults },
});
// Make LLM call
const completion = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: userInput }]
});
const response = completion.choices[0].message.content;
await tryguardy.completeSession({
sessionId,
success: true,
promptTokens: completion.usage?.prompt_tokens,
completionTokens: completion.usage?.completion_tokens,
});
return response;
} catch (error) {
await tryguardy.completeSession({
sessionId,
success: false,
failureReason: error.message,
});
throw error;
}
}Best Practices
Always complete sessions
Call complete_session() or finish() even on errors to ensure data is recorded.
Track meaningful events
Focus on tool calls and decisions, not every line of code.
Include failure reasons
When success=False, always include failure_reason for better diagnosis.
Use consistent agent names
Same agent_name groups sessions together in the dashboard.
Track costs accurately
Use the cost calculation helpers or track real token usage.