AIC: Packages Need an Interface for Coding Agents A developer introduced AIC (Agent Index Convention), a draft protocol for packages to expose an interface for coding agents. The convention separates provider packages, host repositories, and coding agents, addressing issues of ownership, freshness, discovery, and composition when multiple packages share agent-facing context. I develop several tightly related repositories at the same time. Some are reusable SDKs for declarative schemas, infrastructure, stateful workflows, and other domain abstractions. Others are applications that consume several of those SDKs together. The development loop constantly crosses package boundaries. SDK A ──────┐ │ SDK B ──────┼──▶ application │ │ SDK C ──────┘ │ ▲ │ └──── feedback ───┘ I've already written about why I don't think this requires a monorepo, and why I prefer the repository itself to carry the current source of truth: I won't repeat those arguments here. This post starts one layer later. As these SDKs became more agent-aware, each package started needing to tell coding agents how it should be used. I was already using project-local surfaces such as .claude/ , .codex/ , AGENTS.md , and package-specific skills. They are useful. Explicit project-local context works. The maintenance was the awkward part. When an SDK changed, I would tell the agent to update the corresponding instructions, rules, or skills in the consuming repository. That worked too. But after doing it repeatedly across several packages and repositories, I noticed something: My repeated update instructions had quietly become an undocumented protocol. Which files should change? Which source is canonical? What should be copied? What should only be referenced? What belongs to the package, and what belongs to the consuming repository? How should different coding-agent harnesses receive the same package knowledge without creating independent copies? I initially thought I needed a better synchronizer. I now think the problem is one layer higher. Packages already have an interface for programs. They increasingly need an interface for coding agents. I've been calling the protocol I'm using for that interface AIC — Agent Index Convention . It is still a draft from my own development environment. The exact mechanics will change. The boundary it describes feels much more stable. Packages already know how to introduce themselves to programs: package name version API types schemas config CLI A coding agent needs another set of facts: where is the current manual? which rules matter? which skills are available? which files are generated? which commands are safe? which host-specific configuration applies? I think of this as the package's agent-facing interface . The problem appears when several packages expose that interface inside the same host repository. Without a shared convention, each package tends to solve the problem independently. package A ──▶ AGENTS.md package B ──▶ CLAUDE.md package C ──▶ .claude/skills/ package D ──▶ .codex/... Each integration can be perfectly reasonable in isolation. Composition introduces a different set of problems. | Concern | Failure mode | |---|---| | Ownership | one package overwrites human or provider-owned context | | Freshness | copied instructions drift from the installed package | | Discovery | harnesses load different files and directories | | Composition | every package assumes it owns the shared surface | This stopped looking like documentation management. It started looking like package composition. AIC separates three actors: Provider package │ │ declares agent-facing assets ▼ Host repository │ │ exposes them through actual harness loading paths ▼ Coding agent A Provider is a package that supplies agent-facing context. A Host is the repository consuming that package. The provider ships its agent-facing source with the package: provider-package/ ├── agent-index.json ├── AGENTS.md └── skills/ A minimal manifest might look like: { "schema": "agent-index/v1", "package": "@scope/schema-sdk", "version": "0.14.0", "summary": "Declarative schema toolkit", "manual": "AGENTS.md", "skills": { "name": "schema-design", "src": "skills/schema-design" } , "instanceConfig": { "source": "declarative", "readFrom": "schema.config.json", "format": "json", "fields": "runtime", "validation" } } agent-index.json is not another manual. It declares: identity version canonical manual discoverable assets host-resolved facts The useful change for me is that the maintenance contract becomes declarative. Instead of repeatedly telling an agent: Update the Claude and Codex instructions to match the latest SDK behavior. it can inspect a structure closer to: provider ├── canonical manual ├── skills ├── resolved host config └── target loading semantics The update no longer depends on how well I happened to describe the maintenance task that day. This distinction has probably been the most useful part of AIC in actual use. Not all agent-facing assets should cross the package boundary in the same way. | Class | Example | Operation | |---|---|---| Index | identity, version, pointers, resolved config | inject | Referenced | manuals, detailed rules | keep with provider | Materialized | harness-discovered skills | copy deterministically | ┌── Index ─────▶ inject Provider package ─┼── Manual ─────▶ reference └── Skill ─────▶ materialize I originally wanted one mechanism for all three. Actual loading semantics made that abstraction wrong. Copying a manual into the host creates two independently changing truths. installed package v0.14 copied manual v0.13 I've hit enough package version-skew problems elsewhere that I don't want to recreate the same class of bug in the agent-context layer. Here it is worse than ordinary stale documentation. A stale instruction consumed by an agent that can edit code and run commands is executable misinformation. The agent may not be hallucinating at all. It may be behaving perfectly according to the wrong version. So the canonical manual stays with the installed package. The host stores a pointer, not another copy. In practice, this has been one of the more durable AIC decisions: upgrading the package does not require another manual copy to somehow remain synchronized. Skills are different. If a harness discovers a skill only by scanning a particular directory, mentioning its package path is not equivalent to putting it where the harness looks. The asset needs physical presence. So the rule I use is: Reference when read access is enough. Materialize when discovery requires presence. That is more useful than either "copy everything" or "never copy." Context placement should follow actual loading semantics, not an aesthetically uniform abstraction. Of the AIC decisions I've been testing, this asymmetry is one of the ones I currently trust most. Each provider contributes a small namespaced block to the host index. Agent index: @scope/schema-sdk v0.14.0 - Manual: read node modules/@scope/schema-sdk/AGENTS.md - Skills: managed under the harness discovery path - Host config: validation=strict Several providers can coexist: AGENTS.md │ ├── human-owned content ├── @scope/package-a ├── @scope/package-b └── @scope/package-c The central invariant is: A provider owns its namespace, not AGENTS.md . Updating package B may update B's block. It may not: rewrite human content move package A modify package C regenerate the whole file Materialized assets follow the same rule: each provider gets its own collision-safe namespace. This is also something I've been able to test rather than only describe. In the implementations I'm using, foreign provider blocks are preserved rather than normalized into the current provider's representation. Repeating a sync with the same input is tested as a no-op. Providers can also share lock state without one provider flattening another provider's private fields. Those details are intentionally boring. But they are the difference between saying "multiple providers can coexist" and actually letting them coexist. The packages do not need pairwise integrations. Package A does not need to know package B exists. Package B does not need a plugin for package C. They compose because they share an ownership rule. Coordination is expensive. Namespaces are cheap. This is the point where AIC stopped feeling like a synchronizer to me. It started feeling like a package protocol. AIC is not an argument against .claude/ , .codex/ , or other harness-specific locations. I use them because they are useful. The problem was maintaining them independently. I want: ┌── AGENTS.md │ provider source ───────┼── Claude adapter ├── Codex adapter ├── skill discovery adapter └── other thin adapters not: manual ├── Claude copy ├── Codex copy ├── Cursor copy └── another copy Harness-specific files are derived surfaces . The canonical package knowledge remains singular. This also gives the design an escape hatch. If a harness eventually provides a better native mechanism for consuming package-owned instructions or skills, the adapter should disappear. The package boundary does not have to. The adapter layer is expendable. The boundary declaration is not. That distinction matters because harness behavior will probably change faster than package contracts. AIC currently has lifecycle operations roughly like: agent-index sync agent-index check agent-index remove The most important property is idempotence. same provider same version same source same managed host state │ ▼ no-op Running sync twice with identical inputs should not produce a second write, timestamp churn, or Git diff. For materialized assets, AIC tracks both sides: provider source ── hash ──▶ sourceHash host copy ── hash ──▶ destHash That distinguishes: provider upgraded host copy locally edited nothing changed Those states should not all result in "copy again." The original asset is materialized byte-for-byte. Provenance sits beside it rather than being injected into skill frontmatter, scripts, or templates. I don't want sophisticated reconciliation here. I want deterministic ownership with boring failure modes. There is another reason I care about determinism: agents are maintainers too. A human can often infer that two slightly different layouts represent roughly the same convention. An agent benefits more from: one format one ownership rule one lifecycle one source of truth The easier the maintenance structure is to inspect mechanically, the less the next agent session has to reconstruct from prose. This is one place where implementation made the tradeoff clearer. A protocol can define what should be synchronized without guaranteeing that every synchronization happens immediately. I've had cases where a package version and its managed agent state temporarily diverged because a manual step was missed. That is exactly the class of problem AIC is intended to make detectable. It is also evidence that declaring the protocol does not magically remove its maintenance cost. The current split is deliberate: | Operation | Responsibility | |---|---| preflight | cheap version-staleness repair | check | full version and integrity verification | sync | explicit verification and regeneration | The common path stays cheap. The stronger path stays explicit. I prefer that to turning every CLI startup into a full filesystem integrity scan. I commit the generated index, materialized skills, and lock/provenance state. A change like: - Agent index: @scope/schema-sdk v0.13.0 + Agent index: @scope/schema-sdk v0.14.0 changes what the agent can discover. A changed materialized skill can change what the agent can do. I want those changes visible beside the dependency update that caused them. So I think of AIC output more like this: | Artifact | Reviewable state | |---|---| | lockfile | dependency resolution | | generated schema | structural contract | | migration plan | intended transition | | agent index / skill | agent operating context | Generation isn't the problem. Invisible generation is. Keeping generated state fresh naturally leads to automatic repair. This is where I've become deliberately conservative. I don't want dependency installation to silently rewrite host-owned files. I also don't want the first execution of an SDK CLI to decide by itself that the repository has opted into agent integration. So AIC distinguishes adoption from maintenance. first encounter └──▶ warn / explicit sync existing provider + stale version └──▶ repair own namespace managed content locally edited └──▶ preserve + warn CI / read-only filesystem └──▶ don't mutate removed or disabled provider └──▶ stay removed The invariant is: Automation may maintain established ownership. It should not invent ownership. There is a tradeoff. Preflight needs an execution opportunity. If a dependency is upgraded but the relevant provider CLI has not run yet, materialized state can temporarily remain stale. I accept that window today. The alternative would be making package installation mutate the host automatically, which I currently consider the worse ownership boundary. Teams that need a stricter guarantee can run check explicitly or in CI. So preflight does not eliminate drift. It makes the common repair path cheap while leaving full integrity verification explicit. This also removes another piece of my old workflow. I no longer want this: Please update the agent files after this SDK change. to be part of the development procedure. If the relationship is structural, the update rule should be structural too. There is an important qualification. The providers I'm using AIC with today are part of the same development environment. I control both sides of the protocol. That gives me something useful: I can test whether independently versioned packages actually compose through the same rules. It does not yet prove that unrelated third-party package authors will adopt them. So today I would describe AIC as a working convention inside one ecosystem , not an ecosystem-wide standard. The distinction matters because much of the eventual value of a protocol comes from network effects. That is the part I have not demonstrated yet. There are a few other current assumptions. A manual that stays inside the installed package is only useful once the dependency is actually available. On a fresh clone before dependency installation, the pointer can temporarily lead nowhere. I currently accept that because the reference is meant to describe the installed package state. It does mean AIC is not a substitute for dependency availability. AIC relies on an entry point the harness already loads — for example AGENTS.md , an import into it, or a harness-specific discovery directory. It does not solve "how does every possible coding agent discover AIC?" from first principles. That is intentional. I would rather adapt to real loading behavior than introduce another mandatory bootstrap mechanism. A referenced manual is information. A materialized skill can influence what an agent actually does. That makes third-party providers a different trust problem from packages I control myself. Content hashes tell me whether an asset changed. They do not answer who should be trusted to supply that asset. That is one of the areas I would want to make more explicit before treating agent-index/v1 as a third-party ecosystem contract. Agent harnesses are moving quickly. Native packaging for instructions, skills, or package-owned agent context may eventually absorb some of what AIC adapters do today. If that happens, I don't want to defend the current synchronization machinery for its own sake. The parts I expect to survive are smaller: declare the agent-facing package boundary own only your namespace keep canonical knowledge version-bound separate reference from discovery-required materialization make derived state deterministic and reviewable respect prior host ownership decisions The adapter layer is expendable. The boundary declaration is the interesting part. That is also why I don't want to freeze the schema too early. Before asking unrelated providers to adopt it, I would rather make the convention boring inside the repositories I already operate: fewer drift incidents fewer manual repair instructions fewer conventions that exist only in my head If that keeps working, the format has evidence behind it. If the ecosystem converges on a better native mechanism, AIC should become a thin adapter to that mechanism rather than compete with it. The parts I currently think are structural: The parts I expect to change: agent-index.json schemaFor a while, I thought I needed a better way to tell coding agents to keep .claude/ , .codex/ , manuals, and skills synchronized. Eventually I realized that the repeated instruction was itself the missing specification. Packages already know how to introduce themselves to programs. AIC is my attempt to give them a small, composable way to introduce themselves to coding agents.