Skip to content
scsiwygest. ‘26
Sign in
get startedmcpcommunityapiplaygroundswaggersign insign up
project-state·Why a typed substrate beats a wiki for AI agents28 May 2026David Olsson
project-state

Why a typed substrate beats a wiki for AI agents

#design#architecture#obsidian#wiki#ai-agents#substrate#building-in-public

David OlssonDavid Olsson

The most common question about project-state's architecture is some variant of: why not just use Obsidian? Or a wiki? Why invent a new substrate when mature knowledge-management tools already exist?

The answer is that Obsidian and wikis solve a different problem. They are excellent tools for humans building a body of knowledge. They are not good substrates for AI agents doing operational work. The difference is structural, and it matters more than it looks like it should.

What an agent sees when it opens a wiki

A wiki or an Obsidian vault is a graph of markdown pages connected by backlinks. Every node in the graph is prose. A milestone, a decision, a person, a meeting note, and a brainstorm all look the same to the agent — freeform text with [[wikilinks]] pointing at other freeform text.

To do anything useful, the agent has to:

  1. Find the relevant pages by full-text search or link traversal. There is no index that says "give me all milestones where status is at-risk." The agent reads pages and infers which ones are milestones.
  2. Parse the structure from prose. A milestone page might have a due date in the body, or in a YAML frontmatter block, or in a Dataview annotation, or mentioned in a sentence. The agent has to interpret each page to know what it contains.
  3. Trust the shape. Nothing enforces that a milestone page has a due date, a status, or an owner. The agent can't assume any field exists. Every read is a best-effort extraction.
  4. Hope nothing conflicts. Two agents — or two humans — editing the same vault produce file-level conflicts that sync tools handle mechanically but semantic conflicts that nothing catches. Two people updating the same milestone's status at the same time is invisible to Obsidian Sync.

This works for knowledge management because humans are good at interpreting prose and resolving ambiguity. The flexibility is the feature. You don't want your note-taking tool to reject a note because it's missing a required field.

But an AI agent operating on project state is not taking notes. It is reading structured data and performing operations — creating milestones, transitioning phases, generating reports, checking what's overdue. For that job, every interpretive step is a failure mode.

What an agent sees when it opens project-state

project-state is a typed filesystem. Every entity has a kind, a schema, a deterministic filename, and required frontmatter.

A milestone is milestones/M03-prototype-delivery.yaml. The agent doesn't interpret — it reads:

id: M03-prototype-delivery
kind: milestone
status: in_progress
due_date: 2026-06-30
percent_complete: 45
owner: david
created: 2026-04-15T00:00:00Z
last_modified: 2026-05-20T14:30:00Z
last_modified_by: project-milestone-manager

Every field is present because the memory layer refused to write the file without them. The filename is deterministic — derived from the id, not chosen by the author. The kind field tells the agent what schema applies without reading the content.

"Give me all milestones where status is at-risk" is a directory listing plus a YAML parse. No NLP. No inference. No interpretation.

The operations gap

The structural difference matters most when the agent needs to act, not just read.

In a wiki, "create a new milestone" means: decide what page to create, decide what fields to include, write markdown, hope the format matches what other pages look like, hope no one else is creating a milestone at the same time, and manually update whatever index or MOC page tracks milestones.

In project-state, "create a new milestone" is a skill invocation that routes through the memory layer. The memory layer:

  1. Checks for a lockfile. If another agent is writing to a monolithic file, it waits or aborts.
  2. Validates that required fields are present and well-typed.
  3. Writes the file with correct frontmatter timestamps.
  4. Appends one line to logs/activity.ndjson — an immutable audit record.
  5. Updates state.json counters.
  6. Releases the lock.

One coherent operation instead of five fragile file writes. The agent calls the skill; the skill enforces the invariants. The agent doesn't need to know the schema — the skill knows it.

This is the difference between a filesystem and a database with no query language, versus a filesystem that acts as a database with operations. The wiki is the former. The substrate is the latter.

Concurrency is a design-time decision

This is where the gap becomes a chasm for real multi-agent or multi-human workflows.

Obsidian Sync handles file conflicts with last-write-wins or manual merge prompts. That's fine for notes. It is not fine for state. If two agents both update a milestone's percent_complete at the same time and one wins silently, the state is corrupt. No one knows. The next report uses the wrong number.

project-state was designed for a shared drive from day one. The concurrency model has three layers:

File-per-entity isolation. There is no milestones.yaml. There are milestones/M01-*.yaml, milestones/M02-*.yaml — one file per milestone. Two agents working on two different milestones never touch the same file. No conflict possible.

Advisory lockfiles for monolithic state. The few files that are monolithic — manifest.yaml, state.json — use lockfiles with a 300-second TTL. If an agent crashes mid-write, the lock expires and the next agent can proceed.

Optimistic concurrency via timestamps. Every writable file has last_modified. Before writing, the memory layer checks if the file has been modified since the agent last read it. If it has, the write returns CONFLICT instead of clobbering.

None of this is exotic. It's the same discipline any multi-user system uses. The point is that it's built into the substrate rather than bolted on by a sync tool that doesn't understand what the files mean.

The reporting matrix makes the difference concrete

The clearest illustration of why typed state matters is the reporting matrix — the central v2.0 concept.

In a wiki-based system, the question "what reports does the Steering Committee need and when" is answered by a page somewhere, written in prose, that the agent reads and interprets. Maybe it's structured. Maybe it's a table. Maybe it's a paragraph. The agent parses it, infers the cadence, guesses the format, and hopes it understood correctly.

In project-state, the answer is a YAML file:

yaml
entries:
  - id: sc-quarterly-pack
    stakeholder_group: steering-committee
    report: Quarterly SC Pack
    cadence: { kind: quarterly, month_offset: 1, day_of_month: 15 }
    format: docx
    surface: gmail-draft
    generator: project-funder-reporting
    profile: pic-pcais/sc-quarterly

The orchestrator reads this on its scheduled tick. It checks the date. It dispatches the generator. The generator reads the profile, which tells it what sections to include, what format to use, what tone. The output lands as a Gmail draft for human review before sending.

No interpretation. No ambiguity. No risk that the agent misreads a prose description and sends the wrong report to the wrong stakeholder at the wrong time.

Where wikis win

None of this means wikis are bad tools. They are very good tools for the thing they do.

Open-ended knowledge capture — research notes, brainstorming, reference material, learning, creative exploration — is better served by a flexible page-based system than by a schema-enforced substrate. You don't want your thinking constrained by required fields.

Human readability matters. A wiki page about a design decision reads better than a YAML file. Humans browse wikis. They don't browse YAML directories.

Emergent structure is a real benefit. The best wikis start loose and develop structure over time as patterns solidify. That organic evolution is hard to replicate in a typed system where the schema has to be defined up front.

project-state doesn't try to replace any of that. The project-document-curator skill can index external documents — including wiki pages, Google Docs, PDFs, whatever format the knowledge lives in. The project-harvester pulls signals from Slack, Gmail, and Google Docs into the substrate as intel. Creative, unstructured thinking lives wherever you think best.

The distinction is: wiki for knowledge, typed substrate for operational state. An AI agent needs both. They need to be different things.

The design principle underneath

The reason project-state uses typed YAML instead of prose pages isn't a technology preference. It's a design principle: minimize the interpretive work the agent has to do on every operation.

Every time an agent has to read prose and infer structure, there's a probability of misinterpretation. For a single read, that probability is low. For a system that runs hundreds of operations across dozens of sessions — creating milestones, checking phase gates, generating reports, routing notifications, tracking changes — the misinterpretation compounds. Eventually something goes wrong, and no one notices because the error is semantic, not syntactic.

Typed state eliminates that class of error. The agent reads structured data. The schema guarantees the shape. The memory layer enforces the invariants. The operations are well-defined. The audit log records what happened. When something goes wrong, you can trace it.

This is the same reason databases have schemas and APIs have contracts. The wiki model is fine when the reader is a human who can resolve ambiguity in real time. When the reader is an agent that needs to act reliably across sessions without supervision, the interpretation tax becomes the bottleneck.

The substrate pays that tax once — at schema design time — so the agent never pays it at runtime.

Share
𝕏 Post