Type Registry
The Standard Agent Specification provides an extensible type system that enables type-safe references for models, prompts, agents, and tools. Through TypeScript’s declaration merging, implementations can populate type registries to provide autocomplete and compile-time validation.
1. The StandardAgentSpec Namespace
1.1 Overview
The specification declares a global StandardAgentSpec namespace containing type registries. When registries are empty, types fall back to string for flexibility. When populated, types narrow to specific values.
declare global {
namespace StandardAgentSpec {
interface ModelRegistry {}
interface PromptRegistry {}
interface AgentRegistry {}
interface ToolRegistry {}
interface CallableRegistry {}
interface HookIdRegistry {}
type Models = keyof ModelRegistry extends never ? string : keyof ModelRegistry;
type Prompts = keyof PromptRegistry extends never ? string : keyof PromptRegistry;
type Agents = keyof AgentRegistry extends never ? string : keyof AgentRegistry;
type Tools = keyof ToolRegistry extends never ? string : keyof ToolRegistry;
type Callables = keyof CallableRegistry extends never ? string : keyof CallableRegistry;
type HookIds = keyof HookIdRegistry extends never ? string : keyof HookIdRegistry;
}
}
1.2 Registries
| Registry | Purpose | Computed Type |
|---|---|---|
ModelRegistry | Model definition names | StandardAgentSpec.Models |
PromptRegistry | Prompt definition names | StandardAgentSpec.Prompts |
AgentRegistry | Agent definition names | StandardAgentSpec.Agents |
ToolRegistry | Tool definition names | StandardAgentSpec.Tools |
CallableRegistry | All callable items (prompts, agents, tools) | StandardAgentSpec.Callables |
HookIdRegistry | Hook IDs from defineHook() | StandardAgentSpec.HookIds |
1.3 Type Resolution
The computed types use TypeScript conditional types:
type Models = keyof ModelRegistry extends never ? string : keyof ModelRegistry;
Resolution:
- Empty registry:
keyof ModelRegistryisnever, soModelsresolves tostring. - Populated registry:
keyof ModelRegistryis a union of the declared keys, soModelsnarrows to that union.
2. How Types Are Used
2.1 In Model Definitions
The fallbacks property references other models:
interface ModelDefinition<N extends string = string> {
name: N;
// ...
fallbacks?: StandardAgentSpec.Models[];
}
2.2 In Prompt Definitions
Prompts reference models and callables:
interface PromptDefinition<N extends string = string> {
name: N;
model: StandardAgentSpec.Models;
tools?: (
| StandardAgentSpec.Callables
| SubpromptConfig
| PromptToolConfig
| SubagentToolConfig
)[];
// ...
}
interface PromptIncludePart {
type: 'include';
prompt: StandardAgentSpec.Prompts;
}
interface SubpromptConfig<T extends string = StandardAgentSpec.Callables> {
name: T;
// ...
}
interface PromptToolConfig {
name: StandardAgentSpec.Callables;
// ...
}
2.3 In Agent Definitions
Agents reference prompts and callables:
interface SideConfig<
Prompt extends string = StandardAgentSpec.Prompts,
Callable extends string = StandardAgentSpec.Callables,
> {
prompt: Prompt;
stopTool?: Callable;
sessionStop?: SessionToolBinding<Callable>;
sessionFail?: SessionToolBinding<Callable>;
sessionStatus?: SessionToolBinding<Callable>;
// ...
}
interface AgentDefinition<
N extends string = string,
Prompt extends string = StandardAgentSpec.Prompts,
Callable extends string = StandardAgentSpec.Callables,
> {
name: N;
sideA: SideConfig<Prompt, Callable>;
sideB?: SideConfig<Prompt, Callable>;
// ...
}
3. Augmenting the Namespace
3.1 Declaration Merging
TypeScript allows interfaces to be augmented across files. Implementations generate type declarations that add entries to registries:
// Generated by build tools (e.g., .agents/types.d.ts)
declare global {
namespace StandardAgentSpec {
interface ModelRegistry {
'gpt-4o': true;
'claude-3-opus': true;
'gemini-pro': true;
}
interface PromptRegistry {
'customer_support': true;
'data_analyst': true;
}
interface AgentRegistry {
'support_agent': true;
'research_flow': true;
}
interface ToolRegistry {
'search_knowledge_base': true;
'create_ticket': true;
}
interface CallableRegistry {
'customer_support': true;
'data_analyst': true;
'support_agent': true;
'research_flow': true;
'search_knowledge_base': true;
'create_ticket': true;
}
interface HookIdRegistry {
'limit_to_20_messages': true;
'log_tool_calls': true;
'redact_credit_cards': true;
}
}
}
export {};
3.2 Effect of Augmentation
After augmentation, the computed types narrow:
// Before augmentation:
type Models = string;
// After augmentation:
type Models = 'gpt-4o' | 'claude-3-opus' | 'gemini-pro';
3.3 Registry Entry Format
Registry entries use true as a placeholder value:
interface ModelRegistry {
'gpt-4o': true;
'claude-3': true;
}
This pattern enables keyof ModelRegistry to produce the union 'gpt-4o' | 'claude-3'.
4. Implementation Requirements
4.1 Build-Time Generation
Implementations SHOULD generate type declarations at build time by:
- Scanning definition directories (models, prompts, agents, tools)
- Extracting the
nameproperty from each definition - Generating a
.d.tsfile that augments theStandardAgentSpecnamespace
4.2 File Structure
The generated file MUST:
- Use
declare globalto augment the namespace - Include
export {}to make it a module (required for declaration merging) - Be included in the project’s TypeScript configuration
4.3 Example Generation
Given these definitions:
agents/
├── models/
│ ├── gpt_4o.ts # name: 'gpt-4o'
│ └── claude.ts # name: 'claude-3-opus'
├── prompts/
│ └── support.ts # name: 'customer_support'
└── agents/
└── agent.ts # name: 'support_agent'
Generate:
// .agents/types.d.ts
declare global {
namespace StandardAgentSpec {
interface ModelRegistry {
'gpt-4o': true;
'claude-3-opus': true;
}
interface PromptRegistry {
'customer_support': true;
}
interface AgentRegistry {
'support_agent': true;
}
interface ToolRegistry {}
interface CallableRegistry {
'customer_support': true;
'support_agent': true;
}
interface HookIdRegistry {}
}
}
export {};
5. Benefits
5.1 Autocomplete
When registries are populated, IDEs provide autocomplete for valid names:
definePrompt({
name: 'my_prompt',
model: 'gpt-4o', // IDE shows: 'gpt-4o' | 'claude-3-opus' | 'gemini-pro'
tools: ['search_'], // IDE suggests: 'search_knowledge_base'
});
5.2 Compile-Time Errors
TypeScript catches invalid references at compile time:
definePrompt({
name: 'my_prompt',
model: 'gpt-5', // Error: Type '"gpt-5"' is not assignable to type 'Models'
tools: ['invalid_tool'], // Error: Type '"invalid_tool"' is not assignable to type 'Callables'
});
5.3 Refactoring Safety
Renaming a model, prompt, agent, or tool propagates through the registry types. TypeScript flags every stale reference so all callers can be updated in lockstep.
6. Backward Compatibility
6.1 Empty Registries
The type system is designed to be backward compatible:
- Empty registries default to
string - Existing code without type generation continues to work
- Type narrowing is opt-in (only active when registries are populated)
6.2 Gradual Adoption
Projects can adopt type generation incrementally:
- Start with
stringtypes (no generation) - Add type generation when ready
- Fix any type errors that surface
- Enjoy full type safety going forward
7. TypeScript Reference
/**
* Global namespace for Standard Agent Specification types.
* Provides extensible registries that consumers can augment
* via TypeScript's declaration merging.
*/
declare global {
namespace StandardAgentSpec {
/** Registry of model names. Augment to add model names. */
interface ModelRegistry {}
/** Registry of prompt names. Augment to add prompt names. */
interface PromptRegistry {}
/** Registry of agent names. Augment to add agent names. */
interface AgentRegistry {}
/** Registry of tool names. Augment to add tool names. */
interface ToolRegistry {}
/** Registry of all callable items (prompts, agents, tools). */
interface CallableRegistry {}
/** Registry of hook IDs from defineHook(). */
interface HookIdRegistry {}
/** Union of all model names, or string when registry is empty. */
type Models = keyof ModelRegistry extends never ? string : keyof ModelRegistry;
/** Union of all prompt names, or string when registry is empty. */
type Prompts = keyof PromptRegistry extends never ? string : keyof PromptRegistry;
/** Union of all agent names, or string when registry is empty. */
type Agents = keyof AgentRegistry extends never ? string : keyof AgentRegistry;
/** Union of all tool names, or string when registry is empty. */
type Tools = keyof ToolRegistry extends never ? string : keyof ToolRegistry;
/** Union of all callable names, or string when registry is empty. */
type Callables = keyof CallableRegistry extends never ? string : keyof CallableRegistry;
/** Union of all hook IDs, or string when registry is empty. */
type HookIds = keyof HookIdRegistry extends never ? string : keyof HookIdRegistry;
}
}
export {};