
Ten months as the automation engineer behind Dyme — a multi-agent SEO content engine routing two frontier models, plus the browser-automation system that turns a member's travel search into a timely outreach email.
Dyme is a sustainable travel platform. Like every business whose customers arrive through search, it needs a steady supply of articles that are genuinely researched, genuinely useful, and genuinely good enough to publish — and that supply is normally capped by how many writers you can afford.
The obvious answer is "use AI to write the articles", and the obvious answer produces exactly what you would expect: generic text, invented facts, no awareness of what competitors already rank for, and links that point at pages which do not exist. Useless at best, actively damaging to a domain at worst.
Sunil's ambition was more specific than "generate articles". He wanted a system that did the work a good content team does — research the keyword landscape, look at what is already ranking, establish authority, then write — with a human reviewing at the end rather than in the middle.
"We ultimately want to have an AI agent factory, replacing the old ways of building lots of scripts. And being able to interact with any website is a key part of that."
A community workflow existed that did roughly the right shape of thing, sold for about the price of lunch. Asked whether to build an equivalent from scratch, the honest answer was no — buying it and adapting it would cost a fraction of a bespoke build. That advice removed most of a build fee from the engagement. What follows is the work that actually mattered: making a template survive contact with a real environment, real models and a real publishing standard.
The system is organised the way a content department is: a group that researches, a group that checks the claims, and a group that writes. Each is a labelled zone of agents on a single n8n canvas, and work moves left to right between them.
Routing by task rather than picking one model for everything is the difference between an expensive toy and something with a defensible cost per article.
Before a word is written, the system decides what the article should be about and what it is up against.
A keyword agent expands the seed topic across three distinct intents — long-tail, problem-focused and solution-focused — because those surface materially different search demand. A topic agent then fixes the core angle, and a competitor agent identifies who currently owns the term. Everything is arranged into a structured brief before it leaves the zone.
This is the stage most AI content pipelines skip, and it is the reason most AI content is worthless.
A loop walks the research output and runs it through an E-E-A-T fortification agent — experience, expertise, authoritativeness, trust, the criteria search engines actually assess — while a competitor content analyst reads what is already ranking. Both are equipped with live retrieval tools rather than being asked to recall: one extracts the content of a specific page, the other searches the open web.
Giving an agent a search tool instead of trusting its recall is what separates a claim the reviewer can check from a sentence that merely sounds right. By the time anything reaches the writing stage, it is anchored to sources that existed this week.
Only now does anything get written — and even then it is assembled in stages rather than produced in one shot.
An authoritative-resource agent gathers citable sources, an outline architect structures the piece, and the Expert Article Weaver writes the draft against the brief, the verified research and the outline. A tone check reviews the result, then two link passes insert external citations and internal links.
Internal linking turned out not to be a prompting problem at all. Asking a model to link to a site's pages invites it to invent plausible URLs. The fix was to stop asking and start supplying: the approved link list is passed into the workflow as data the writing agent must choose from, so a fabricated URL is not an option available to it.
Articles were arriving truncated. Separately, the instruction to insert internal links appeared to be ignored. They looked like unrelated failures — a prose problem and a prompt problem.
Both were the same ceiling. The model was hitting its default output cap and stopping before it reached the end of the article, which is where the link instructions applied. Raising the limit fixed the truncation and the "ignored" links at once — with the further finding that pushing much higher requires switching to a streaming HTTP request, because the standard node does not stream by default.
"The article got cut off because by default, the number of tokens for the output was less than required… I think points 2 and 3 were both caused by this."— Waqass, tracing the root cause
The other hard part was getting an article out of the machine and into something a human could edit. The workflow produced HTML; the Google Docs node appends whatever it is given as literal text, so drafts arrived as visible markup. Prompting the model to emit Docs-native formatting did not work, and neither did a transform node.
The solution was to stop fighting the node and add a rendering step outside it: append the raw HTML to the document, call a bound Apps Script exposed as a web app to convert it into real formatting, then strip the markup that was left behind.
It is not elegant, and the constraint is worth stating plainly: because the script is bound to one document, drafts accumulate in that document rather than each getting their own. That was the accepted trade for a formatting step nobody has to do by hand.
Alongside the content engine, the same ten months produced a system with a much simpler premise: when a member searches for travel on the platform, reach out while they are still deciding.
The searches sat behind a login with no API. That ruled out an HTTP node, and it ruled out the off-the-shelf scrapers — none of them could get through the sign-in. Flagging that early mattered more than working around it quietly, because it changed what the client was buying.
The client's preference was clear: keep it inside the agent platform rather than accumulate standalone scripts. So instead of a server nobody wanted to maintain, the browser automation was built as a custom Apify actor from an empty Python template — hosted, callable over an API, and therefore usable as just another node.
Two failures in production, both about identity. Contacts were being emailed twice: the workflow matched rows by email address, and the same address appeared on several rows, so it kept marking only the first one as sent. Matching on row number instead fixed it. The second was subtler — the "find new searches since last time" logic assumed the first row marked sent was the most recent, which stopped being true the moment anyone edited the sheet by hand. It now scans every record for the true latest timestamp.
Enforcing an exact word count on the finished article was never made reliable. Prompt constraints were tried, and a dedicated rewriting agent was added specifically to bring drafts into range; neither held consistently. It was handed back with that stated plainly rather than papered over, and the client took it on from there. Length discipline in long-form generation remains a genuinely unsolved edge, and claiming otherwise would have cost him time discovering it himself.
Just tested it and works great — thanks! Let me think through some more projects for you.
What began as a single defined task became a standing relationship across three separate systems, and the conversation has continued past the end of the work itself — into what a longer-term arrangement might look like.
Most of that came from the unglamorous parts: saying when something should be bought rather than built, naming a blocker the day it appeared instead of absorbing it silently, and being straight about the one requirement that never fully worked.
"Want to be supportive of you given all the great work you've done for us."
Want content or outreach that runs as a system, with your team reviewing the output instead of producing it?
Book a call with Botify →