I want to be upfront: the piece you might be reading right now could have been drafted by an AI agent. If the byline says "AI-assisted," that's what happened. The system, the prompts, the editorial judgment, and the final published text are mine. The research synthesis and first draft might not be.
Here is how it works and why I built it this way.
The problem with AI-generated blog content
Most AI content pipelines fail in one of two ways. Either they produce generic, low-signal content that no one wants to read — the kind that fills search results but adds no value. Or they automate publication entirely, which means the AI's confident hallucinations become published facts under your name.
I wanted neither. I wanted a system that could accelerate the research-heavy parts of writing — synthesising technical topics, finding relevant examples, drafting structured arguments — while keeping me in the loop for everything that requires actual judgment.
Architecture
The agent is a cron job in the NestJS backend that runs twice a week. It makes a POST request to /api/agent/stories with a Bearer token — the same endpoint described in the README. The endpoint is protected by the AgentKeyGuard, which validates the Bearer token against the AGENT_API_KEY environment variable.
Every submission from the agent lands as a draft — this is enforced at the service layer, not just by convention. The agent DTO doesn't even have a status field. The service hardcodes status: 'draft' and aiAssisted: true on every agent submission. The agent cannot publish directly, even if it tries to.
// Agent submissions always land as draft
async agentCreate(dto: AgentStoryDto): Promise<StoryDocument> {
const slug = await this.generateSlug(dto.title);
return new this.storyModel({
...dto,
slug,
status: 'draft', // enforced — not from DTO
aiAssisted: true, // enforced — not from DTO
publishedAt: null,
}).save();
}
The prompt structure
The agent prompt is domain-specific. It knows the blog's voice, the typical structure of pieces I've written, and a list of topics I've flagged as interesting. The prompt instructs the model to write in first person, to include concrete technical examples, to avoid abstract advice, and to flag any claims it's uncertain about with a marker I can find with a quick Ctrl+F before publishing.
Uncertain claims are marked with [VERIFY: ...] in the draft. This is the most important convention in the whole system. A confident AI hallucination published under my name is a reputation problem. A flagged uncertain claim that I catch in review is not.
The review workflow
When the agent creates a draft, I get a Resend notification email with the title and the first two paragraphs. I review it in the admin dashboard. The TipTap editor makes inline editing fast — I can fix phrasing, remove uncertain claims I can't verify, or add my own perspective before publishing. If the draft is weak, I delete it and move on. The agent doesn't know or care.
What the agent is genuinely good at
Research-heavy explanatory content. "How does X work" and "What are the tradeoffs between Y and Z" pieces where the value is in the synthesis, not in a specific personal experience. It's not good at opinion pieces, personal project reflections, or anything that requires knowing something about what I was actually thinking when I made a decision. Those I still write entirely myself.
The labels
Every AI-assisted piece on this site carries the "AI-assisted" badge you see in the metadata. It's not a disclaimer in small print — it's a first-class piece of the story metadata displayed at the top of every post. I think readers deserve to know.