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

RegistryPurposeComputed Type
ModelRegistryModel definition namesStandardAgentSpec.Models
PromptRegistryPrompt definition namesStandardAgentSpec.Prompts
AgentRegistryAgent definition namesStandardAgentSpec.Agents
ToolRegistryTool definition namesStandardAgentSpec.Tools
CallableRegistryAll 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 ModelRegistry is never, so Models equals string
  • Populated registry: keyof ModelRegistry is a union of keys, so Models narrows 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:

  1. Scanning definition directories (models, prompts, agents, tools)
  2. Extracting the name property from each definition
  3. Generating a .d.ts file that augments the StandardAgentSpec namespace

4.2 File Structure

The generated file MUST:

  1. Use declare global to augment the namespace
  2. Include export {} to make it a module (required for declaration merging)
  3. 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:

  1. Start with string types (no generation)
  2. Add type generation when ready
  3. Fix any type errors that surface
  4. 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 {};