FORM NOT VOID, MIND NO CORE

Chapter 2: Filesystem as Self

2026.08.10

An agent's "who you are" should be an editable file, not a constant written in someone else's code.


Pattern Layer

2.1 Two Paradigms of Agent Identity

When you open an AI agent's system prompt, you will most likely see lines like this:

You are ChatGPT, a large language model trained by OpenAI.
You are Claude, an AI assistant created by Anthropic.

These lines define the agent's self-perception — or at least the self-perception it presents to the user. It is told what it is, what it cannot pretend to be, and what principles it should follow.

The problem is: these lines are written in the provider's code. Users cannot modify them, extend them, or audit them. Every rule of conduct you trust is built on the premise that "the provider did not lie."

This is the first paradigm: hard-coded identity.

Hard-coded identity has two irreplaceable advantages. First, determinism — no matter who starts the agent or when, its identity statement is always the same. The provider can guarantee version consistency of the identity statement. Second, simplicity — no filesystem needed, no load path needed, no reload mechanism needed; it is just a single string constant.

But its disadvantages are equally clear:

  • Not modifiable: You cannot adjust an agent's identity statement to suit your project's needs
  • Not auditable: You cannot open a file in the code repository, point to a line, and say "this is its code of conduct"
  • Not cross-session persistent: When the session ends, the identity statement is discarded along with the context — the next session loads the same string, but the preferences "for this project" that you established in yesterday's session are gone

The second paradigm: file-defined identity.

When the agent starts, its identity is not read from an API constant — it is read from files on disk. Users modify these files to modify the agent's identity.

DimensionHard-Coded IdentityFile-Defined Identity
ModificationRequires provider updateEdit file, then reload
AuditCheck provider announcementCheck git log
Cross-sessionReloaded each timeFile persists
DeterminismIdentical every sessionMay vary with file version

This is not a comparison of "which is more advanced" — the two paradigms correspond to different trust models. Hard-coded identity trusts the provider's deployment pipeline. File-defined identity trusts the integrity of the user's filesystem. For locally running agent systems where the user has full control over files, file-defined identity is the more natural fit.

2.2 Why Files?

On the path of file-defined identity, the next question is: why files, and not a database, environment variables, or a network configuration service?

Modifiability. Files can be modified with any text editor. No database client, no API call, no privileged access required. Anyone who can write Markdown can modify AGENTS.md. This means the barrier is lowered to the minimum — modifying an identity statement is not an operations task; it is a documentation task.

Auditability. Once files are in git version control, every change's diff is visible in PR review. An auditor can see "what constraints were added to this agent's identity last week" and "who changed its code of conduct and when." Database records can also be audited, but they require a dedicated audit module — git is an already-existing audit infrastructure.

Cross-session persistence. Sessions end. Sessions can be closed, compressed, or deleted. But files on disk do not disappear when a session ends — the next session starts with the agent reading the same set of files. Unless the user explicitly deletes or modifies them.

Version controllability. Files can be branched, reverted, and tagged. You can use git checkout to go back to last week's version of AGENTS.md and see what identity the agent had at that time. Database versioning can also achieve this, but it requires a dedicated migration mechanism.

Why not a database? — Because the agent's identity information does not need transaction support or ACID guarantees. Identity files follow a "single writer, multiple reads" access pattern. When you modify an identity file, no other process is modifying it simultaneously (because the agent's filesystem is designed for single-user use). For this scenario, the filesystem is lighter, faster, and easier to audit than a database.

2.3 File Granularity: What Goes in Files, What Goes in JSON, What Goes in Memory

File-defined identity does not mean stuffing everything into files. Different kinds of data have different carriers:

Data stored in files: requires human audit and modification.

  • AGENTS.md (plain text Markdown) — identity statement. Needs to be read, modified, and PR-reviewed by humans
  • CONTEXT.md (plain text Markdown) — glossary. Needs manual maintenance; diffs should be clearly visible
  • Each .md file under skills/ — procedural knowledge. Can be written manually or generated by the agent
  • Each code directory + manifest under capabilities/ — executable artifacts. Generated by the agent, reviewed by the user

Data stored in JSON: primarily machine-read, secondarily human-read.

  • Session files (JSON message tree) — complete record of conversation history. Machine parsing performance is the priority
  • Work Graph files (JSON milestone graph) — persisted task plans. Read and written by the milestone tool
  • Memory files (JSON key-value) — cross-session persistent memory. Written by the agent using the memory tool

Data stored in memory: does not need persistence, discarded when the session ends.

  • Session allowlist (runtime permission cache) — permission choices made by the user in the current conversation
  • Sub-agent context (temporary objects of nested AgentLoop) — destroyed when the sub-agent exits

The selection principle for the three types of carriers is: who consumes the data, how frequently does it change, and does it need to survive across sessions? Files = human-read + low-frequency change + cross-session. JSON = machine-read + medium-frequency change + cross-session. Memory = machine-read + high-frequency change + does not cross sessions.


Case Layer

2.4 AGENTS.md: Structure of the Identity Statement

AGENTS.md is the core of the agent identity file system. It is not merely a "who you are" declaration — it has three layers of content:

First layer: Identity statement. Approximately 200 characters, stating the agent's role, core principles, and behavioral boundaries. It begins with "You are CodeCoder, an autonomous AI software engineer," and subsequent paragraphs elaborate on core behavioral principles.

Second layer: Core principles. A set of principles the agent references in every turn decision. This includes the full definition of "filesystem as self," the meaning of the "Tool / Skill / Capability" three-part architecture, and safety boundaries and stop conditions.

Third layer: Immutable constraints. This constraint lives in the same file as the identity statement — "You are an AI agent and cannot pretend to be human." This is not an additional compliance-priority rule; it is a hard ceiling on the identity statement. The existence of this constraint prevents identity forgery through simply modifying the "You are X" field.

The content of AGENTS.md is injected into the system prompt via the Registry at startup. At the beginning of every turn, the agent has "read" this identity statement. But note — it is not injected once and never changes. When /reload is executed, the Registry rescans the system and the changes to AGENTS.md take effect immediately.

2.5 CONTEXT.md: The Glossary

If AGENTS.md defines "who you are," CONTEXT.md defines "what you know." It is essentially a project glossary, where each entry contains:

  • Term name (English, the form used in code and conversation)
  • Definition (Chinese, no more than 200 characters, precisely describing the meaning)
  • Boundary (when this term applies / does not apply)
  • Synonyms that must not be used (Avoid list)

A typical CONTEXT.md entry:

## Session

Persistent JSON conversation file. Contains messages, schema_version, and creation time.
_Avoid_: dialogue, conversation history, chat log (these terms lack sufficient precision).

## Tool

Native primitive compiled into the binary, cannot be added or removed at runtime. 26 total.
_Avoid_: function, operation, action (these terms do not trigger the tool registration path when used outside of CONTEXT.md).

At the time of writing, CodeCoder's CONTEXT.md has over 100 entries. That sounds modest, but every entry corresponds to a term misuse found during code review. CONTEXT.md is not written to look good — it is a constraint system that grew out of engineering practice. Every time you find the agent using an incorrect term in its output, you add one Avoid entry to CONTEXT.md.

2.6 skills/ + capabilities/ + memory/

The identity file system includes more than just AGENTS.md and CONTEXT.md — it also includes three types of growing identity components:

skills/ — Procedural knowledge. Each .md file is a methodology (e.g., debugging steps, code review workflow, work graph planning approach). A Skill is the agent's "way of thinking" — it does not change what the agent can do, but how the agent makes decisions. The skills/ directory is fully injected into the system prompt at startup, so the agent always has access to the methodological knowledge it has been granted during each turn.

capabilities/ — Executable artifacts. Each Capability contains code and a manifest (declaring Environment and Lifecycle). It goes further than a Skill — not only telling the agent how to do something, but giving the agent a new pair of "hands." The capabilities/ directory is not automatically injected into the system prompt — the agent must explicitly invoke it via the run_capability tool.

memory/ — Persistent key-value memory. This is not a JSON copy of session history — it is small pieces of information that the agent itself decides to remember. memory write key=preferred_lint value=clippy::pedantic — in a later session, the agent can retrieve this value via memory read preferred_lint. Both writing and reading are triggered by the agent; the system does not participate proactively.

The positioning of these three file types within the identity file system:

TypeStorage FormatInjection TimingModification FrequencyHuman Audit
AGENTS.mdMarkdownStartup / reloadLow (policy changes)Strongly recommended
CONTEXT.mdMarkdownStartup / reloadMedium (project evolution)Strongly recommended
skills/One Markdown per fileStartup / reloadMedium (skill sedimentation)Optional
capabilities/Code + manifestOn-demandLowStrongly recommended
memory/JSON key-valueOn-demand read/writeHigh (daily use)Optional

2.7 Registry Scanning and Hot Reload

The identity file system needs a mechanism to "load" and "reload." This is the Registry.

The Registry performs a full scan at agent startup:

  1. Read the skills/ directory, collect all .md files
  2. Read the prompts/ directory, collect all .md files (draft layer)
  3. Read the capabilities/ directory, collect all manifests (.yaml / .json)
  4. Read AGENTS.md and CONTEXT.md
  5. Build the collected content into a resident directory table (filename → content digest)
  6. Inject the contents of the resident directory table into the system prompt

The /reload command performs the same steps as the startup scan — but without restarting the process, only re-executing steps 1-6. This means that while the agent is running, users can:

  • Add a new Skill file → /reload → the agent has this knowledge on the next turn
  • Modify a constraint in AGENTS.md → /reload → the agent's code of conduct updates immediately
  • Delete an outdated Capability → /reload → the agent no longer lists it as an available capability

The key design point of hot reload is: additions and deletions do not trigger permission changes. Permission keys are bound to tool names, not file entries. Even if you delete a Capability, the agent cannot bypass the permission system to execute it — because the Registry simply leaves it off the available list, rather than revoking its permission.

2.8 Mini Demo

The following script demonstrates a minimal viable implementation of "filesystem as self." No Rust compiler or AI provider API key needed.

# 1. Create the identity file
echo "You are a code review assistant. Focus only on security issues." > AGENTS.md

# 2. Write a Skill
mkdir -p skills
cat > skills/security-review.md << 'EOF'
When reviewing code, follow this order:
1. Input validation — is user input handled correctly
2. Authentication and authorization — are permission checks performed at every layer
3. Data leakage — is sensitive information exposed
4. Injection risks — SQL/command/OS injection
EOF

# 3. Start the agent (actual startup command depends on your implementation)
# Agent reads AGENTS.md and the skills/ directory at startup

# 4. Modify AGENTS.md to add a rule
echo "Extra rule: never approve policy changes that introduce println! into the main branch." >> AGENTS.md

# 5. Trigger reload
# On the next message, the agent's behavior has already changed

The core idea does not depend on any specific programming language or AI provider. You only need an agent launcher that can read files and a /reload command.


ADR Deep Reading

Evolution of the Registry: From Hard-Coded List to File Scanning

ADR 0020 (Skills and Capabilities Registry) documents CodeCoder's evolution of the identity file system from a "hard-coded tool list" to "filesystem scanning."

Before the Registry existed, the Skills available to the agent were hard-coded in the source:

fn built_in_skills() -> Vec<SkillDescriptor> {
    vec![
        SkillDescriptor { name: "debug-causal", content: include_str!("../skills/debug-causal.md") },
        SkillDescriptor { name: "security-review", content: include_str!("../skills/security-review.md") },
    ]
}

Every addition or modification of a Skill required recompilation. For developers, this was not a big problem — the CI pipeline handles it. But for the goal of "letting the agent write its own Skills and register them," the compilation cycle was too long. After an agent generated a Skill file, it could not "wait until the next compilation for it to take effect."

The introduction of the Registry changed this mechanism to runtime file scanning: instead of including file contents at compile time, directories are read at startup. Compile-time injection became runtime loading — modifying a file equals modifying identity became possible.

ADR 0025 (Prompt as Skill Draft Tier) added a draft layer on top of the Registry. The original design had only two states: unwritten knowledge / formal Skill. Skill content generated by the agent was written directly into skills/, with no intermediate state. But in practice, it was found that the first version of a Skill generated by the agent was often of low quality — lacking terminological consistency, immature step ordering, and vague acceptance criteria. The introduction of the prompts/ draft layer provided a buffer between "finished writing" and "ready for active use." Drafts can only be activated on demand via use_skill and are not automatically injected at startup like formal Skills. Only after explicit promotion via promote_prompt are they merged into skills/.

This was not a large architectural change — the core modification was only a few dozen lines of code — but it filled a gap in the identity file system: the path from "does not exist" to "active and usable" needs an intermediate state. Without this gap, the agent would either use raw generated output as a Skill (uncontrollable quality) or wait for manual compilation (delaying the activation of autonomous capability).


Next, we move into Chapters 3 through 5, diving deep into the runtime design of the agent kernel: event-driven architecture, tool permissions, and sub-agent cancellation.