DEV Community

Cover image for AIC: Packages Need an Interface for Coding Agents
Takafumi Endo | ROUTE06
Takafumi Endo | ROUTE06

Posted on

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 boundaries.

 SDK A ──────┐
             │
 SDK B ──────┼──▶ application
             │        │
 SDK C ──────┘        │
    ▲                 │
    └──── feedback ───┘
Enter fullscreen mode Exit fullscreen mode

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.

The missing package interface

Packages already know how to introduce themselves to programs:

package name
version
API
types
schemas
config
CLI
Enter fullscreen mode Exit fullscreen mode

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?
Enter fullscreen mode Exit fullscreen mode

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/...
Enter fullscreen mode Exit fullscreen mode

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.

The AIC model

AIC separates three actors:

Provider package
      │
      │ declares agent-facing assets
      ▼
Host repository
      │
      │ exposes them through actual harness loading paths
      ▼
Coding agent
Enter fullscreen mode Exit fullscreen mode

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/
Enter fullscreen mode Exit fullscreen mode

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"]
  }
}
Enter fullscreen mode Exit fullscreen mode

agent-index.json is not another manual.

It declares:

identity
version
canonical manual
discoverable assets
host-resolved facts
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

it can inspect a structure closer to:

provider
  ├── canonical manual
  ├── skills
  ├── resolved host config
  └── target loading semantics
Enter fullscreen mode Exit fullscreen mode

The update no longer depends on how well I happened to describe the maintenance task that day.

Inject, reference, or materialize

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
Enter fullscreen mode Exit fullscreen mode

I originally wanted one mechanism for all three.

Actual loading semantics made that abstraction wrong.

Reference what can remain version-bound

Copying a manual into the host creates two independently changing truths.

installed package   v0.14
copied manual       v0.13
Enter fullscreen mode Exit fullscreen mode

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.

Materialize what discovery requires

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.

One host index, many providers

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
Enter fullscreen mode Exit fullscreen mode

Several providers can coexist:

AGENTS.md
│
├── human-owned content
├── @scope/package-a
├── @scope/package-b
└── @scope/package-c
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Harness-specific files are derived surfaces

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
Enter fullscreen mode Exit fullscreen mode

not:

manual
├── Claude copy
├── Codex copy
├── Cursor copy
└── another copy
Enter fullscreen mode Exit fullscreen mode

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.

Sync should be boring

AIC currently has lifecycle operations roughly like:

agent-index sync
agent-index check
agent-index remove
Enter fullscreen mode Exit fullscreen mode

The most important property is idempotence.

same provider
same version
same source
same managed host state
       │
       ▼
     no-op
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

That distinguishes:

provider upgraded
host copy locally edited
nothing changed
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

The easier the maintenance structure is to inspect mechanically, the less the next agent session has to reconstruct from prose.

Determinism does not eliminate drift

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.

Generated agent state belongs in Git

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
Enter fullscreen mode Exit fullscreen mode

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.

Preflight repairs; it doesn't claim ownership

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
Enter fullscreen mode Exit fullscreen mode

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.
Enter fullscreen mode Exit fullscreen mode

to be part of the development procedure.

If the relationship is structural, the update rule should be structural too.

Where this actually works today

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.

Referenced assets require an installed package

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 does not invent universal discovery

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.

Materialized assets expand the trust boundary

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.

What I expect to survive

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

What is still draft

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.

Top comments (0)