Tools
Utility tools available from the primfunctions package that you can use anywhere in your agent code.
Logger#
primfunctions.logger lets you log messages from anywhere in your agent code without needing to yield a LogEvent back to the handler.
from primfunctions.logger import logger
Methods#
All methods accept a message string and an optional attributes dictionary for additional context.
logger.info("Lead qualified", {"lead_id": "abc123"}) logger.warn("Retrying API call", {"attempt": 2}) logger.error("Payment failed", {"order_id": "456"}) logger.debug("Entering fallback branch")
| Method | Description |
|---|---|
logger.info(message, attributes=None) | General information |
logger.warn(message, attributes=None) | Warnings |
logger.error(message, attributes=None) | Errors |
logger.debug(message, attributes=None) | Debug details |
Where Logs Appear#
- Events tab — Each call emits a
LogEventthat appears in the session details Events tab with the log level, message, and the source file and line number where it was called. - Traces tab — If tracing is enabled, each log entry also creates a span in the Traces tab.
Example#
from primfunctions.events import Event, StartEvent, TextEvent, TextToSpeechEvent from primfunctions.context import Context from primfunctions.logger import logger async def handler(event: Event, context: Context): if isinstance(event, StartEvent): logger.info("Session started") yield TextToSpeechEvent(text="Hello!") if isinstance(event, TextEvent): user_message = event.data.get("text", "N/A") logger.info("Received user message", {"text": user_message}) result = await process_message(user_message) if result.get("error"): logger.error("Processing failed", {"error": result["error"]}) else: logger.debug("Processing succeeded", {"tokens": result["token_count"]}) yield TextToSpeechEvent(text=result["reply"])
Local Development#
When running locally outside the sandbox, the logger falls back to printing to the console:
[info] Session started
[error] Processing failed
Tracer#
primfunctions.tracer provides a decorator you can apply to any Python function to trace its inputs and outputs. If tracing is not enabled, the decorator is a no-op.
from primfunctions.tracer import tracer
@tracer.tool#
Decorate a function to trace its execution. Works with both sync and async functions.
@tracer.tool def fetch_user(user_id: str) -> dict: # inputs and outputs are captured automatically return db.get_user(user_id) @tracer.tool async def search_products(query: str) -> list: return await catalog.search(query)
You can optionally pass name, description, and parameters for richer trace metadata:
@tracer.tool(name="lookup_order", description="Look up an order by ID") async def lookup_order(order_id: str) -> dict: return await orders.get(order_id)
Where Traces Appear#
Traced function calls appear as spans in the Traces tab of the session details page, showing the function name, inputs, outputs, and duration.
Example#
from primfunctions.events import Event, StartEvent, TextToSpeechEvent from primfunctions.context import Context from primfunctions.logger import logger from primfunctions.tracer import tracer @tracer.tool async def get_account_balance(account_id: str) -> dict: logger.info("Fetching balance", {"account_id": account_id}) balance = await accounts_api.get_balance(account_id) return {"account_id": account_id, "balance": balance} async def handler(event: Event, context: Context): if isinstance(event, StartEvent): account_id = context.data.get("account_id") result = await get_account_balance(account_id) yield TextToSpeechEvent(text=f"Your balance is ${result['balance']}")
Local Development#
When tracing is not enabled, @tracer.tool has no effect — the decorated function runs exactly as if the decorator were not present.
