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 {}
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;
}
}
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 |
1.3 Type Resolution
The computed types use TypeScript conditional types:
type Models = keyof ModelRegistry extends never ? string : keyof ModelRegistry;
This means:
- Empty registry:
keyof ModelRegistryisnever, soModelsequalsstring - Populated registry:
keyof ModelRegistryis a union of 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)[];
// ...
}
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;
endSessionTool?: 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;
}
}
}
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;
}
}
}
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 type system. TypeScript will flag all references that need updating.
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 {}
/** 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;
}
}
export {};