AIC: Packages Need an Interface for Coding Agents
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 bou

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: AI Agents Don't Need a Monorepo. They Need a Readable Codebase The Repo Is the Context: Why Agents Don't Need History 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: packages need an explicit agent-facing interface multiple providers need namespace ownership canonical manuals should remain version-bound to their packages referenced and discoverable assets need different persistence semantics harness-specific surfaces should be derived rather than independent sources of truth synchronization should be deterministic and reviewable maintenance structures should be easy for agents themselves to inspect automatic repair should respect established ownership The parts I expect to change: the exact agent-index.json schema workspace and nested-repository scoping harness adapters skill discovery paths preflight policy integrity and trust rules for third-party providers For 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.
Key Takeaways
- β’I develop several tightly related repositories at the same time. Some are reusable SDKs for declarative schemas, infrastructure, stateful workflows, and other domain abstractions
- β’This story was reported by Dev.to, covering developments in the dev space.
- β’AI advancements continue to reshape industries β read the full article on Dev.to for complete coverage.
π Continue reading the full article:
Read Full Article on Dev.to βShare this article


