Ron Bronson

PBBG Content Schema

A content architecture for browser games built with agents. JSON Schemas, scoped writing policies, and a linter that keep three things apart: the words on the buttons, the words in the story, and the numbers that decide what happens. I pulled it out of Coalition and published it on its own.

Problem
A scene may depend on an earlier promise. Agents needed a way to find that relationship.
System
A content architecture for browser games built with agents: JSON Schemas, writing policies, a linter, a skill and an MCP server.
Mechanics
Rules, story, interface text and writing policy each have one owner. Text never holds its own numbers. {turns} points to a declared cost, so changing the rule changes every sentence that names it.
Stack
JSON Schema with Ajv; Node 20 CLI; MCP; Agent Skill. No network or model calls.
Result
Version 0.6.0. An agent installs it with one command and checks its own edits. Every build of Coalition checks the game’s copy with it.

This demo runs PBBG’s real renderer and validator, with action costs linked for the example. Coalition checks its exported content on each build. The game engine still controls actions and outcomes.

The problem

Coalition already kept its simulation, interface, and rendering code separate. Its content needed a clearer structure. As coding agents added scenes, I wanted the story to remain coherent and the interface text to meet the same standards I use for websites. Scenes need references to the choices, conditions, and events around them, so agents can find those relationships without reconstructing them from scattered code and prose.

What it separates

A bundle declares four kinds of thing with four owners. Game definitions own costs, requirements, conditions, and typed effects. Narrative owns scene text, dialogue, and who’s speaking. Interface owns labels, headings, status lines, and errors. A content policy supplies the writing rules for each, scoped by domain and pattern. No terminal punctuation on a label. No action label over six words. No raw HTML in prose.

Text never carries a number of its own. A sentence template binds {turns} to a declared action cost. It can bind a name to a public entity, or a value to a fact the reader’s role and phase are allowed to see. Change the cost in the game definitions and every sentence that names it changes with it. Declare a fact as hidden from a role and the renderer refuses to put it in that role’s text. That last part is what Coalition’s government side needs: a player who must never see the candidate’s real position while the engine knows it exactly.

The checker

A local CLI validates a bundle against the schema, then runs reference and policy checks. It catches duplicate IDs, dangling references between scenes and events, and conditions on facts that don’t exist. It catches placeholders with no binding, speakers that aren’t declared, and text that a role shouldn’t receive. Every finding carries a rule ID, a JSON pointer, a message, and a repair hint. The whole report is available as JSON, so an agent can read it as a tool result. A second command, guidance, returns the rules the checker enforces plus the writing guidance for one domain and pattern. A host can put the policy in front of a model before it edits rather than after.

There are fourteen content patterns across the two domains. Action label, navigation or heading, action preview, blocked action, and arrangement status. Report, dialogue, scene, and card. Action result, technical error, empty state, tutorial, and ending. Every one of them exists because Coalition has it.

How it’s built

Schemas
Two JSON Schemas, one for bundles and one for policies, validated with Ajv. Version 0.5.0 rejects unknown fields and versions, so a misspelled key fails instead of becoming ignored data.
Reference code
A small Node module for validation, role and phase projection, text rendering, and task guidance, and a CLI over it. Node 20 or later, no network calls, no model calls, no telemetry.
Example
A fictional transit station with no connection to Coalition’s setting, so the format is shown without the game.
Policy
An editable base policy with separate interface and narrative guidance. A project replaces it whole with --policy; there is no inheritance to reason about.
License
Eclipse Public License 2.0, with the plain-language and design sources attributed in the docs.

Building it with agents

Define the release and its boundaries

I chose to release the reusable architecture before building another game around it. I directed the work to stay independent of other editorial tools and to use a neutral example. Codex prepared the initial package: schemas, writing policies, reference checks, text rendering, a command-line tool, tests, and adoption documentation.

The action record also keeps an owner decision that changed the agent’s first choice. Codex picked an MIT license. I specified the Eclipse Public License 2.0, and the record notes the change and the package updates that followed.

Give the next agent a bounded extension

Next I asked for an Agent Skill and a Model Context Protocol server so agents could use the package directly. Claude added that access layer and left the content format, schemas, and existing validation rules unchanged.

The server exposes five read-only tools. An agent can retrieve writing guidance, validate a content bundle, inspect schemas, check which facts a role may see, and preview rendered text. Each tool calls the existing library functions, so the command-line checks and the agent’s checks stay consistent.

Record what was tested and what wasn’t finished

The implementation records describe checks for invalid references, hidden facts, action-cost rendering, and policy scope. The second stage added tests for the server and documented a connection through an MCP client.

Coalition supplied the original problem and the extraction reference, but at that point its inline content hadn’t moved to the package. Passing the checks proved the structure held. They didn’t test the writing itself, string coverage, or the game integration.

Handle a failure without inventing a diagnosis

The first publishing attempt failed after the package checks passed. I asked Claude to investigate. It could inspect the failed step but couldn’t see the raw log or the secret settings, so it recorded that the cause was unconfirmed.

Claude changed the workflow to check authentication before publishing and to surface errors on the run page. Its handoff documented the change, the evidence still needed, and the step I had to take to rerun the workflow.

At each stage I set the purpose and scope and made the calls that needed an owner. The agents wrote the code and tests and explained their technical choices. Every stage ended with a record of what was finished and checked, and what was still open.

What it doesn’t do

It doesn’t simulate anything. The host engine evaluates conditions, runs effects, keeps the clock, and decides disclosure. Declaring a fact hidden in a JSON file is not server security. It doesn’t extract strings from an existing game, migrate saves, or check whether a story contradicts itself. Coalition writes its text in its own content files. Every build turns them into a bundle in this format and runs the checker over it. If the check fails, the build stops. The game’s rules aren’t in that bundle yet. No second game uses the schema, so it hasn’t yet been tested outside the game it came from.

Repo: quarterback/pbbg-content-schema. Related: agentexperience.ax.