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

```typescript
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:

```typescript
type Models = keyof ModelRegistry extends never ? string : keyof ModelRegistry;
```

Resolution:
- **Empty registry**: `keyof ModelRegistry` is `never`, so `Models` resolves to `string`.
- **Populated registry**: `keyof ModelRegistry` is a union of the declared keys, so `Models` narrows to that union.

## 2. How Types Are Used

### 2.1 In Model Definitions

The `fallbacks` property references other models:

```typescript
interface ModelDefinition<N extends string = string> {
  name: N;
  // ...
  fallbacks?: StandardAgentSpec.Models[];
}
```

### 2.2 In Prompt Definitions

Prompts reference models and callables:

```typescript
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:

```typescript
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:

```typescript
// 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:

```typescript
// 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:

```typescript
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:

```typescript
// .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:

```typescript
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:

```typescript
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:

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

```typescript
/**
 * 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 {};
```