· 2 min read · ← All posts
Ardan Labs Go Agents Security Audit

Field notes from working through example 27 of Ardan Labs’ Ultimate AI course by Bill Kennedy and Florin Pățan (Apache 2.0). My fork: PratikDhanave/ai-training. Thank you Bill and Florin for teaching this material — the patterns in this post are derived from the course; the production reflections at the end are mine.

What the example teaches

Agents call tools. Tools sometimes call other tools (an MCP server that itself calls an upstream API). Without limits, the chain can recurse, loop, or escalate privileges. The example wires a budget (max depth, max cost, max wall time) and an audit log that records every node in the chain.

What it looks like

type Budget struct {
    MaxDepth      int
    MaxCostMicros int64
    MaxDuration   time.Duration
}

type AuditEntry struct {
    Depth      int
    ParentID   string
    Tool       string
    Args       string  // truncated
    Cost       int64
    DurationMs int64
}

func RunTool(ctx context.Context, budget *Budget, parentID, tool string, args any) (result any, err error) {
    if budget.Depth >= budget.MaxDepth {
        return nil, ErrDepthExceeded
    }
    // ... cost check, time check ...
    budget.Depth++
    defer func() { budget.Depth-- }()

    audit.Log(AuditEntry{Depth: budget.Depth, ParentID: parentID, Tool: tool, ...})
    return tools[tool].Run(ctx, args)
}

What I learned

The depth cap matters more than the cost cap. Cost has a natural ceiling (you’ll notice the bill). Depth doesn’t — an agent stuck in a 1000-deep recursion finishes “successfully” with no visible alarm because every step succeeds. The depth check is what makes that visible.

Audit trail per chain step is the only way to debug. When an agent does something weird, you need the full call graph. A flat audit log doesn’t help; the parent-pointer in each entry lets you reconstruct the tree.

Production connection

Genie’s pkg/auth/elevation (the PCSE PAM analog post on May 26) borrows the same audit shape — hash-chained entries with parent pointers. Reading this example crystallised the pattern; the implementation in Genie is the production-grade version with FREE-AI alignment.


Credit & reference. This post is field notes on example 27 from Ardan Labs’ Ultimate AI by Bill Kennedy + Florin Pățan, licensed Apache 2.0. The original example: cmd/examples/example27-chain-escalation/. My fork with notes: PratikDhanave/ai-training. Highly recommend the course for anyone building AI applications in Go — the material is rigorous and the Kronk + yzma + llama.cpp pipeline gives you hardware-accelerated local inference end-to-end. Thank you, Bill and Florin.

← Back to all posts