Skip to main content
← Back to blog

We built brand compliance as code — and you should too

A PDF of brand guidelines nobody reads won't protect the brand. A BRAND.md the machines enforce will.

Photo by 2H Media on Unsplash

Somewhere in your organization there's a PDF of brand guidelines. It says never use the word "agency," your tone is "warm but professional," CTAs end with a period not an exclamation. Nobody reads it. The new copywriter ships "our agency offers disruptive synergies" and nobody catches it until the post has three days on LinkedIn.

Multiply that by a thousand when the writers are AI. The speed at which they generate content is exactly the speed at which they can break your brand. A PDF doesn't scale. Compliance as code does.

BRAND.md: the brand in machine-readable form

The first step is moving the brand guide into a format machines can read without ambiguity. In Agentikas it's a markdown file with specific sections:

## Terminology

### Use (preferred terms)
- "laboratorio" / "lab"
- "ingenieros" / "engineers"
- "WebMCP"
- "open source"

### Avoid (banned terms)
- "agencia" / "agency"
- "consultora" / "consultancy"
- "transformación digital" / "digital transformation"
- "sinergia" / "synergy"
- "disruptivo" / "disruptive"
- "revolucionario" / "revolutionary"

The format is plain on purpose: the brand author doesn't need to be a programmer. Edit the markdown, commit, the next posts validate against the new rule. No deploy, no coordination, no ticket.

The reviewer: regex with plural and gender awareness

The first instinct was obvious: hand the post to a second model and ask it "validate this matches the brand guide." That worked 80% of the time. The other 20% broke creatively — the model "forgot" a banned term or "allowed" it because it felt fine in context. And it cost a dollar per hundred posts.

The alternative we ended up with is deterministic: regex with linguistic awareness. A ~200-line TypeScript library that does three things:

  1. Reads the banned-terms list from the blog's BRAND.md.
  2. For each term, generates morphological variants — plurals (agency → agencies), gender (consultant → consultanta), derivatives (disruptive → disruptives).
  3. Walks the post HTML skipping content inside <code> or <pre> (a post about Cloudflare can mention "consultancy" in a code example without breaking).

The output is structured:

{
  "score": 78,
  "violations": [
    {
      "term": "agency",
      "found_as": "agencies",
      "context": "...our partner agencies...",
      "suggestion": "labs"
    }
  ],
  "warnings": [
    { "type": "tone", "issue": "Sentence too corporate", "snippet": "..." }
  ],
  "passed": false
}

Three fields matter in practice: the score (0-100), the violations with exact context, and the suggested substitutions. Threshold for auto-publish: 90. Between 70 and 89 the editor highlights for the author. Below, regenerate.

The detail that matters: morphological variants

The first prototype only matched exact terms. You banned "agency" and the reviewer let "agencies," "agencial," "Agency" pass through. Zero practical protection.

The variants layer is what turns the rule into a rule. For Spanish we generate:

  • Singular and plural (agencia / agencias)
  • Case-insensitive
  • Gender if the term is an adjective (disruptivo / disruptiva / disruptivos / disruptivas)
  • Explicit derivative families (sinergia → sinérgico, sinérgica)

For English, similar but simpler — regular pluralization covers 90%, irregulars get declared when they appear.

It's not perfect. It doesn't replace an LLM-based tone linter. But it catches 95% of real violations in under 100ms, free.

Why deterministic, not LLM

There's a reasonable case for using an LLM to validate: it catches nuance, picks up tone, "understands" context. All true. But three reasons regex wins for brand:

  1. Speed. 100ms vs. 2 seconds. In a live editor where the author rewrites and revalidates ten times a minute, the difference is night and day.
  2. Predictability. Same input, same output, every time. When an LLM approves a post today and rejects the same post tomorrow, you lose author trust instantly.
  3. Zero cost. Every generation passes through the reviewer. If every review costs tokens, you multiply platform cost. If it costs local CPU, marginal cost is indistinguishable from zero.

The LLM has its place — reviewing tone, suggesting rewrites, catching semantic problems. But as a publish gate, deterministic wins. You write the rule once and enforce it a billion times without drift.

Next step: LLM reviewer as second tier

Today the deterministic reviewer is the primary defense. There's a second tier, optional and per-blog configurable: an LLM with a custom reviewer_role (defined by the author) that does a tone pass. It doesn't block publishing — it suggests improvements. The equivalent of "someone read it before you hit publish" without that someone needing to exist.

That second tier isn't in production yet. The first tier — deterministic regex — is, and it catches enough that no post has shipped to LinkedIn with "synergy" since it existed.


The brand reviewer and the BRAND.md template live in github.com/agentikas/agentikas-skills, MIT license. Fork, edit the list, plug in your brand. And if you find a morphological variant we missed, send a PR.

Comments

Loading comments…