How Kimi Code's Wire Vocabulary System Handles Model Definitions and Cross‑Reducers
The wire vocabulary system uses defineModel to register type‑safe state containers and defineReducer or defineProjection to create derived state that automatically updates when source models change, with built‑in cycle detection via a dependency graph.
The wire vocabulary is the central state management layer in MoonshotAI's Kimi Code, enabling agents to share data across the entire platform. This system combines declarative model definitions with reactive cross‑model reducers, giving agents a robust, type‑safe way to expose and derive state. The implementation lives in the packages/agent-core-v2 directory and powers everything from simple counters to complex multi‑model views.
DefineModel: Declaring State with Type Safety
Every piece of state that an agent exposes starts with defineModel. This function registers a model type (a TypeScript interface) alongside a default value, creating the foundation for reactive state management.
// packages/agent-core-v2/src/wire/model.ts
defineModel<CounterState>({
key: 'counter',
defaultValue: { count: 0 }
})
The registration is stored in the wire record under a unique key constant: AGENT_WIRE_RECORD_KEY. At runtime, the IWireService creates a model store for each definition, exposing access through wire.getModel(Model) and mutations through op descriptors—generated functions like counterAdd or tagsAdd that describe state transitions.
Key characteristics of model definitions:
- Type‑safe: The generic parameter ensures compile‑time checks on state shape
- Key‑addressable: Each model has a unique string key for serialization and lookup
- Op‑driven: Updates happen through descriptors rather than direct mutation
Cross‑Reducers: Deriving State Across Models
When state depends on multiple models, the wire vocabulary provides defineReducer and the newer defineProjection. These cross‑reducers compute derived values by watching any number of source models.
// packages/agent-core-v2/src/wire/reducer.ts
defineReducer({
models: [CounterModel, TagsModel],
compute: (counter, tags) => ({
summary: `${tags.active}: ${counter.count}`
})
})
A cross‑reducer receives the current values of all referenced models and returns a derived result. The wire service:
- Tracks dependencies between models and reducers in a dependency graph
- Re‑evaluates the reducer automatically when any source model changes
- Caches the result under its own model key for consistent access
- Guards against cycles—attempts to create cyclic dependencies raise a
CycleError
This reactive, graph‑based approach ensures derived state stays consistent without manual synchronization.
Wire Service: Orchestrating Updates and Events
The IWireService implementation coordinates the entire lifecycle. When an agent starts, it reads the manifest (generated by gen:wire-manifest) to discover all models and reducers belonging to that agent.
The dispatch flow in packages/agent-core-v2/src/wire/wireService.ts:
// Dispatch an op to update a model
wire.dispatch(counterAdd({ by: 3 }));
// Internally, the service:
// 1. Applies the op to CounterModel
// 2. Runs reducers that depend on CounterModel
// 3. Emits events like wire.test.counter_changed
After each dispatch, the service applies the operation to the target model, recomputes affected reducers, and broadcasts events so other components can react to state changes.
Testing the Wire Vocabulary System
The test suite validates the complete flow across multiple files.
packages/agent-core-v2/test/wire/wireService.test.ts demonstrates:
- Model registration and
wire.getModel()access - Op dispatch and state updates
- Cross‑reducer evaluation when dependencies change
CycleErrorwhen reducers would create circular dependencies
packages/agent-core-v2/test/wire/wire-compat.test.ts ensures the JSON‑L round‑trip preserves both model state and reducer outputs, verifying serialization compatibility across the platform.
Key Source Files
| Purpose | File |
|---|---|
Model definition API (defineModel) |
packages/agent-core-v2/src/wire/model.ts |
Cross‑reducer API (defineReducer, defineProjection) |
packages/agent-core-v2/src/wire/reducer.ts |
| Wire service orchestration | packages/agent-core-v2/src/wire/wireService.ts |
| Integration tests for models and reducers | packages/agent-core-v2/test/wire/wireService.test.ts |
| JSON‑L compatibility validation | packages/agent-core-v2/test/wire/wire-compat.test.ts |
Summary
defineModelregisters type‑safe state containers with unique keys and default values- Op descriptors provide structured, traceable state mutations
defineReducer/defineProjectioncreate reactive derived state across multiple models- Dependency graph tracking ensures automatic updates while preventing cycles via
CycleError - Event emission lets platform components react to state changes
- JSON‑L serialization preserves state and derived values for persistence and compatibility
Frequently Asked Questions
What happens when two reducers depend on the same model?
Both reducers re‑evaluate automatically when the source model changes. The wire service processes reducers in dependency order and caches each result under its own model key, so multiple downstream consumers see consistent derived values without redundant computation.
Can reducers depend on other reducers?
Yes, reducers can chain—one reducer's output becomes another's input. The wire service builds a complete dependency graph and detects cycles. Any attempt to create a circular dependency throws CycleError during registration, preventing infinite update loops at runtime.
How does defineProjection differ from defineReducer?
defineProjection is the newer API for cross‑model derivation, offering improved type inference and cleaner syntax. Both serve the same core purpose of reactive state computation, but projections align with modern Kimi Code patterns and receive better tooling support in the gen:wire-manifest generator.
Where is the wire state actually stored?
The IWireService maintains model stores in memory during agent execution, keyed by AGENT_WIRE_RECORD_KEY. For persistence, the JSON‑L format handles serialization as demonstrated in wire-compat.test.ts, enabling state restoration across sessions without losing reducer‑derived values.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →