0Pricing
AI Agents · Lesson

Logging Tool Calls and Inputs/Outputs

What to capture per step: tool name, input args, output, latency, error, and parent span id.

Logging Tool Calls and Inputs/Outputs is a free AI Agents lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the AI Agents learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What to Log Per Step

For each span, capture:

  • Step name (llm_call, tool_call, retrieve)
  • Inputs (messages, tool args, query)
  • Outputs (response, tool result)
  • Metadata (model, latency, token counts, cost)
  • Error info if failed

Hand-Rolled Span Helper

Without a framework, a minimal helper:

from contextlib import contextmanager
import time, uuid

@contextmanager
def span(name, trace_id, parent_id=None):
    span_id = str(uuid.uuid4())
    start = time.time()
    record = {'trace_id': trace_id, 'span_id': span_id, 'parent_id': parent_id, 'name': name, 'start': start}
    try:
        yield record
    except Exception as e:
        record['error'] = str(e)
        raise
    finally:
        record['duration_ms'] = (time.time() - start) * 1000
        save_span(record)

Using It

trace_id = str(uuid.uuid4())
with span('llm_call_planner', trace_id) as s:
    s['model'] = 'gpt-4o-mini'
    s['messages_in'] = messages
    response = client.chat.completions.create(model='gpt-4o-mini', messages=messages)
    s['response'] = response.choices[0].message.content
    s['tokens_in'] = response.usage.prompt_tokens
    s['tokens_out'] = response.usage.completion_tokens

Span Nesting

Pass parent_id down so spans form a tree:

with span('agent_step', trace_id) as parent:
    with span('llm_call', trace_id, parent_id=parent['span_id']):
        ...
    with span('tool_call:search', trace_id, parent_id=parent['span_id']):
        ...

Tool Call Logging

Specifically for tool calls, log:

  • Tool name
  • Arguments (JSON)
  • Result (JSON, possibly truncated)
  • Latency
  • Error (if any)

Truncate Big Payloads

Some tool results are huge (200KB HTML). Truncate before storing:

def safe_payload(obj, max_chars=8000):
    s = json.dumps(obj)
    return s if len(s) <= max_chars else s[:max_chars] + '...[truncated]'

PII Redaction

Strip personal info before storing:

import re
EMAIL_RE = re.compile(r'[\w\.-]+@[\w\.-]+')

def redact(text):
    return EMAIL_RE.sub('[email]', text)

print(redact("Contact me at alice@example.com for details."))

Structured Log Output

Emit one JSON record per span — pipe to ELK, Loki, Datadog, or BigQuery:

import json
import sys

def save_span(record):
    print(json.dumps(record), file=sys.stderr, flush=True)

demo_record = {'span': 'call_llm', 'duration_ms': 120, 'ok': True}
save_span(demo_record)
print("Logged span:", json.dumps(demo_record))

Correlate With User Sessions

Include a session_id and user_id in every span so you can filter traces by user later.

Sampling

For high-volume agents, sample:

import random

def should_trace(user_id):
    return random.random() < 0.10  # 10% of traces
# Always trace errors and slow runs.

random.seed(42)
sampled = sum(should_trace(i) for i in range(1000))
print(f"Traced {sampled} out of 1000 calls (~10% target)")

Replay from Traces

Save complete inputs (messages, tools, args) so you can re-run a trace with a new prompt to test improvements. This is the foundation of eval-driven development.

Truncate Big Payloads?

Why truncate large tool outputs in logs?

Recap

Every step, every input, every output — structured, nested, sampled. This is the raw material for everything else in observability.

Frequently asked questions

Is the “Logging Tool Calls and Inputs/Outputs” lesson free?

Yes — the full text of “Logging Tool Calls and Inputs/Outputs” is free to read here on the web, and the AI Agents course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the AI Agents course, upgrade to CoddyKit PRO.

What will I learn in “Logging Tool Calls and Inputs/Outputs”?

What to capture per step: tool name, input args, output, latency, error, and parent span id. You practise AI Agents with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start AI Agents?

No prior experience is required. AI Agents on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Logging Tool Calls and Inputs/Outputs” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this AI Agents lesson?

Yes. Every AI Agents lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Why You Need Tracing for Agents
  2. Logging Tool Calls and Inputs/Outputs
  3. Latency and Cost per Step
  4. Visualising Agent Runs (Langfuse, LangSmith)
← Back to AI Agents