<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Ship AI]]></title><description><![CDATA[Ship AI]]></description><link>https://shipai.hashnode.dev</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1593680282896/kNC7E8IR4.png</url><title>Ship AI</title><link>https://shipai.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 12:45:08 GMT</lastBuildDate><atom:link href="https://shipai.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[A one-page evidence log for AI agents (free template)]]></title><description><![CDATA[When an agent does something it shouldn't, somebody eventually asks one question: what safeguards did you have?
Most teams answer from memory. "We had guardrails." "The system prompt tells it not to t]]></description><link>https://shipai.hashnode.dev/a-one-page-evidence-log-for-ai-agents-free-template</link><guid isPermaLink="true">https://shipai.hashnode.dev/a-one-page-evidence-log-for-ai-agents-free-template</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Security]]></category><category><![CDATA[llm]]></category><dc:creator><![CDATA[Mitch Marshall]]></dc:creator><pubDate>Thu, 08 Oct 2026 20:14:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6ac7f8c04be1e63a0ffcdca0/c0fea399-ad89-4787-8c38-774f79315128.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When an agent does something it shouldn't, somebody eventually asks one question: what safeguards did you have?</p>
<p>Most teams answer from memory. "We had guardrails." "The system prompt tells it not to touch prod." "We'd have caught it." All of these might be true. None of them is something you can show anyone.</p>
<p>There's also some new pressure behind the question. The Hawley/Murphy AI agent accountability bill was introduced on Oct 1. It is not law, and it may never be. The phrase "reasonable safeguards" comes up in the conversation around it, but nobody has said what counts. When the definition is that vague, the only thing you control is your own record: what you checked, when you checked it, and who did it.</p>
<p>This isn't legal advice. It's an engineering habit, and one you'd want anyway the first time an agent does something weird at 2am.</p>
<h2>The template</h2>
<p>One page per agent. Copy it into your repo as <code>EVIDENCE.md</code>, paste it into a doc, or print it and write on it. The rule that makes it work: <strong>if you didn't run it, leave the row blank.</strong> A blank row tells the truth. A backfilled date doesn't.</p>
<h3>Operator Evidence Log</h3>
<p>Agent / system: __________  Env: __________  Owner: __________</p>
<p><strong>1. Network / tool allowlists</strong></p>
<p>What the agent can reach: domains, DNS record types, tools, write scopes. Review again whenever the surface changes.</p>
<table>
<thead>
<tr>
<th>Allowed (domains / DNS / tools / write scopes)</th>
<th>Date reviewed</th>
<th>Reviewed by</th>
<th>Version / commit</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>2. Kill-switch / auto-stop tests</strong></p>
<table>
<thead>
<tr>
<th>Date</th>
<th>Trigger used</th>
<th>Time-to-stop</th>
<th>Pass / fail</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>3. Incident timestamps</strong></p>
<table>
<thead>
<tr>
<th>Detected at</th>
<th>Alerted at</th>
<th>Stopped at</th>
<th>Who paged</th>
<th>Data / systems touched</th>
<th>Follow-up</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p><strong>4. Credentials held outside the agent workload</strong></p>
<table>
<thead>
<tr>
<th>Yes / no</th>
<th>Where held (vault, host env, human-only path, etc.)</th>
<th>Date checked</th>
<th>Checked by</th>
<th>Notes</th>
</tr>
</thead>
<tbody><tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>One row per review, test, or incident.</p>
<h2>How to fill each section</h2>
<h3>Allowlists</h3>
<p>Write down what is actually allowed, not what you meant to allow. Pull it from the config or the egress policy that's live, then record the commit it came from. Each time someone adds a tool or a write scope, that's a new row.</p>
<p>A bad entry:</p>
<blockquote>
<p>"egress restricted" | Q3 | team | n/a | looks fine</p>
</blockquote>
<p>A good entry:</p>
<blockquote>
<p>api.payments-sandbox.test (write: refunds), mail.internal (send: templated). Removed pastebin.com, *.githubusercontent.com. Metadata IP 169.254.169.254 denied | 2026-09-30 | oncall | a19f03d | 14 entries down to 9</p>
</blockquote>
<p>The good one can be checked. Someone can open commit a19f03d and see whether it matches.</p>
<h3>Kill-switch tests</h3>
<p>The trap here is testing the stop on an idle agent. An idle agent always stops. That test tells you nothing.</p>
<p>Run it with work in flight. Queue a few tool calls, fire the stop, and measure two numbers: how long until the agent halted, and how many calls executed after you hit stop. Pass means zero calls after stop.</p>
<p>Here's an illustrative sandbox example of why the second number matters. The stop flag gets checked between plan steps. A batch of three calls was queued before the stop, so those three calls run anyway, spread over about 40 seconds, before the next step boundary reads the flag. If you only measure "did it eventually stop," that test passes. Moving the check into the tool executor, so it runs before every individual call and cancels whatever is pending, gets you to zero calls after stop and a time-to-stop in the hundreds of milliseconds.</p>
<pre><code class="language-python">def run(call):
    if stop_flag.is_set():
        batch.cancel_pending()
        raise Halted(call.id)
    return call.execute()
</code></pre>
<p>A bad entry:</p>
<blockquote>
<p>Sept | manual | fast | pass | worked</p>
</blockquote>
<p>A good entry:</p>
<blockquote>
<p>2026-09-24 14:02:10 | API /stop, 3 calls queued | 412 ms | pass | 0 calls after stop, commit 7c41e2a</p>
</blockquote>
<h3>Incident timestamps</h3>
<p>Detected, alerted, stopped. The gap between detected and stopped is your exposure window, and it's the number people will ask about first. Write the timestamps down the same day, from logs if you can. Times reconstructed a month later from Slack scrollback are mostly guesses.</p>
<p>Also write down what was touched. "Sandbox ledger table, 11 rows" is useful. "Some data" is not.</p>
<p>A bad entry:</p>
<blockquote>
<p>afternoon | ? | ~15 min later | someone | db | fixed</p>
</blockquote>
<p>A good entry:</p>
<blockquote>
<p>14:31:05 | 14:31:40 | 14:32:02 | on-call via pager | sandbox ledger, wrong table, 11 rows | PR to scope writes by table, ticket OPS-212</p>
</blockquote>
<h3>Credentials outside the workload</h3>
<p>If the agent process can read a credential, the agent can use it in ways you didn't plan for. That includes passing it to a tool you didn't expect, or writing it into a log. Record where each credential lives and confirm it isn't sitting in the agent's environment.</p>
<p>A bad entry:</p>
<blockquote>
<p>yes | secure | | | should be ok</p>
</blockquote>
<p>A good entry:</p>
<blockquote>
<p>yes | payments key in vault, fetched by the tool proxy, not in agent env | 2026-10-02 | oncall | checked <code>env</code> inside agent container, no secrets present</p>
</blockquote>
<h2>Why bother if it's not required</h2>
<p>Because every time this comes up, the conversation is the same. Someone asks what you had in place, and the honest answer is a shrug plus a few vague claims. Four short tables turn that into dates, commits, and numbers. It takes maybe ten minutes per review, and the kill-switch test is the only one that takes real setup.</p>
<p>Start with the kill-switch test. It's the one most likely to surprise you.</p>
<hr />
<p>Disclosure: I sell the full Agent Debug Checklist ($19), and this log is page 8 of it: <a href="https://marshalleet6.gumroad.com/l/hgkgsa">https://marshalleet6.gumroad.com/l/hgkgsa</a></p>
]]></content:encoded></item></channel></rss>