
Securing AI agent tool access
This post is a working skeleton, not finished writing. It exists so the frontmatter schema above is visible in a real file — copy it to start a new post, then replace everything below.
Frontmatter fields
Every field here is validated at build time by src/content.config.ts. A typo in a
field name, or a missing required field, fails the build rather than silently
publishing a broken post.
title— required. Rendered as the post<h1>and the browser tab title.description— required. Used in the blog index and in social link previews.pubDate— required. Any parseable date string;'Aug 12 2026'is the template’s convention. Posts are sorted newest-first by this value.updatedDate— optional. Add it when you materially revise a published post and the layout shows an “updated” line.heroImage— optional. A path relative to this file, intosrc/assets/. Astro optimises it at build time, which is why it’s an import path and not a URL.
Structure that tends to work
Open with the problem and why it was hard, not with background. Show the thing that broke. Then the fix, and what it cost.
Code blocks, tables, and images all render through the shared post layout:
# Deny by default; every tool call is an explicit grant.
ALLOWED_TOOLS = frozenset({"read_file", "list_dir"})
def authorize(tool_name: str) -> bool:
return tool_name in ALLOWED_TOOLS
The slug
The URL comes from the filename: this file is securing-ai-agent-tool-access.md, so it
publishes at /blog/securing-ai-agent-tool-access/. Renaming the file changes the URL,
so pick the slug before you share the link anywhere.