# AriaFlow Config Guide

A comprehensive guide to creating and managing AriaFlow agent configurations.

## Overview

The AriaFlow Config package (`@ariaflowagents/config`) provides:
- Configuration loading from `ariaflow.jsonc` files
- Agent and flow definition parsing
- Tool registration and loading
- Runtime creation from config

## Installation

```bash
npm install @ariaflowagents/config
```

## Configuration File

### Basic Structure

```jsonc
{
  "$schema": "https://mithushancj.com/config.json",
  "name": "my-agent",
  "version": "1.0.0",
  "runtime": {
    "defaultAgent": "chat",
    "defaultModel": "default"
  },
  "models": {
    "default": "openai:gpt-4o-mini"
  },
  "agents": { /* ... */ },
  "tools": { /* ... */ },
  "providers": { /* ... */ }
}
```

## Runtime Configuration

### Default Agent & Model

```jsonc
{
  "runtime": {
    "defaultAgent": "chat",
    "defaultModel": "default"
  }
}
```

### Model Registry

Define available models with providers:

```jsonc
{
  "models": {
    "default": "openai:gpt-4o-mini",
    "gpt-4": "openai:gpt-4",
    "claude-3": "anthropic:claude-3-5-sonnet-20241022"
  }
}
```

### Auto Retrieve (always-on)

Calls a retriever tool before every model run and injects the context.

```jsonc
{
  "runtime": {
    "autoRetrieve": {
      "type": "tool",
      "toolName": "cag_retrieve"
    }
  }
}
```

### Structured Triage

Force triage responses into a schema and route without leaking triage text.

```jsonc
{
  "runtime": {
    "triageMode": "structured",
    "triageAgent": "triage"
  }
}
```

### Always Route Through Triage

Useful when every user turn should be re-routed.

```jsonc
{
  "runtime": {
    "alwaysRouteThroughTriage": true
  }
}
```

## Agents

Agents are the core components that handle user interactions.

### LLM Agent

```jsonc
{
  "agents": {
    "chat": {
      "type": "llm",
      "description": "A helpful assistant",
      "prompt": {
        "inline": "You are a helpful assistant. Be concise."
      },
      "tools": ["search", "calculator"]
    }
  }
}
```

### Triage Agent

Routes users to specialized agents:

```jsonc
{
  "agents": {
    "triage": {
      "type": "triage",
      "description": "Routes customers to the right department",
      "prompt": { "file": "./prompts/triage.md" },
      "routes": [
        {
          "agentId": "sales",
          "description": "Handles sales inquiries"
        },
        {
          "agentId": "support",
          "description": "Handles support issues"
        }
      ],
      "defaultAgent": "sales"
    }
  }
}
```

### Flow Agent

Guided workflow agents:

```jsonc
{
  "agents": {
    "booking": {
      "type": "flow",
      "description": "Hotel booking flow",
      "prompt": { "file": "./prompts/booking.md" },
      "flowRef": "booking-flow",
      "mode": "hybrid"
    }
  }
}
```

### Inline Prompt

For simple agents, use inline prompts:

```jsonc
{
  "agents": {
    "chat": {
      "type": "llm",
      "description": "A helpful assistant",
      "prompt": {
        "inline": "You are a helpful assistant. Be concise and friendly."
      }
    }
  }
}
```

### File-based Prompt

For complex prompts, use external files:

```jsonc
{
  "agents": {
    "support": {
      "type": "llm",
      "description": "Customer support",
      "prompt": { "file": "./prompts/support.md" }
    }
  }
}
```

Create the prompt file:

```markdown
# System Prompt

You are a customer support agent for our company.

## Guidelines
- Be empathetic and patient
- Always verify customer identity before sharing sensitive info
- Escalate complex issues to human agents

## Tools Available
- create_ticket: Create support tickets
```

### Template-based Prompt

Use a built-in prompt template and customize sections:

```jsonc
{
  "agents": {
    "triage": {
      "type": "triage",
      "description": "Routes customers to the right team",
      "prompt": {
        "template": "triage-agent",
        "customize": {
          "goal": "Route users to the right specialist.",
          "guardrails": "Never answer non-domain questions."
        }
      }
    }
  }
}
```

## Tools

### External Tools

Define tools that agents can use:

```jsonc
{
  "tools": {
    "search": {
      "type": "module",
      "entry": "./tools/search/index.ts"
    },
    "calculator": {
      "type": "module",
      "entry": "./tools/calculator/index.ts"
    }
  }
}
```

Tool implementation (`tools/search/index.ts`):

```typescript
import type { ToolDefinition } from '@ariaflowagents/core';

export const tool: ToolDefinition = {
  description: 'Search for information',
  inputSchema: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'Search query' }
    },
    required: ['query']
  },
  execute: async (input: unknown) => {
    const { query } = input as { query: string };
    // Implementation
    return { results: [...] };
  }
};

export default tool;
```

### Skill Loader

Load skills from a directory:

```jsonc
{
  "tools": {
    "skill": {
      "type": "skill-loader",
      "paths": ["./skill"]
    }
  }
}
```

## Flows

Define reusable workflow patterns:

```jsonc
{
  "flows": {
    "booking-flow": {
      "entry": "start",
      "defaultRolePrompt": "You are a booking assistant.",
      "nodes": [
        {
          "id": "start",
          "nodeType": "start",
          "addGlobalPrompt": true,
          "prompt": "Welcome. What date would you like to book?"
        },
        {
          "id": "collect_time",
          "nodeType": "agent",
          "prompt": "What time works for you?"
        },
        {
          "id": "end_call",
          "nodeType": "end",
          "addGlobalPrompt": false,
          "prompt": "Thanks, your booking is complete."
        }
      ],
      "transitions": [
        {
          "from": "start",
          "to": "collect_time",
          "on": "to_collect_time",
          "contract": {
            "label": "Move to collect time",
            "conditionText": "After user provides a valid date.",
            "toolOnly": true,
            "requiresUserTurn": true
          }
        },
        {
          "from": "collect_time",
          "to": "end_call",
          "on": "to_end_call",
          "contract": {
            "label": "Finish booking",
            "conditionText": "After user confirms final booking details.",
            "toolOnly": true,
            "requiresUserTurn": true
          }
        }
      ]
    }
  }
}
```

Flow validation is enforced at load time:
- `nodes` must exist and have unique ids
- node prompts must be non-empty
- transition `from`/`to` must reference existing nodes
- transition must define `on` or `condition`
- at most one `nodeType: "start"` and one `nodeType: "global"`

### Generate a Flow Scaffold (CLI)

```bash
ariaflow flow generate --use-case "medical appointment scheduling" --out ./.ariaflow/flow/appointments.json
```

Useful options:
- `--id <flow-id>`
- `--direction inbound|outbound`
- `--agent-name <name>`
- `--llm` (enable model-authored prompts)
- `--model <id>` (default: `gpt-5-mini`; OpenAI models such as `gpt-5-mini`, `gpt-4.1`, or `openai:gpt-4.1`)
- `--llm-mode hybrid|full` (default: `hybrid`)
- `--context-file <path>` (YAML/MD/TXT domain context)
- `--timeout-ms <n>`
- `--out-ts <path>` (emit typed TypeScript flow module for code-first agents)
- `--ts-const <name>` (const name in emitted TS module)
- `--force`

Hybrid mode behavior:
- Static sections remain fixed (structure, critical rules, transitions).
- Only domain-specific blocks vary (overall use-case details and main-agenda tasks/questions).
- This keeps outputs closer to production templates while still adapting per use case.

Code-first usage:
- Use `--out-ts` to generate a typed `FlowConfig` module you can import directly in TypeScript agents.
- This keeps generator output use-case agnostic and reusable across config-first and code-first paths.

LLM provider env var:
- OpenAI models require `OPENAI_API_KEY`

## Providers

Configure API providers:

```jsonc
{
  "providers": {
    "openai": {
      "apiKey": "OPENAI_API_KEY",
      "baseUrl": "https://api.openai.com/v1"
    },
    "anthropic": {
      "apiKey": "ANTHROPIC_API_KEY"
    }
  }
}
```

## Loading Configuration

### Basic Loading

```typescript
import { loadAriaflowConfig } from '@ariaflowagents/config';

const config = await loadAriaflowConfig({
  configPath: './ariaflow.jsonc'
});
```

### With Model Registry

```typescript
import { loadAriaflowConfigWithResult } from '@ariaflowagents/config';
import { openai } from '@ai-sdk/openai';

const model = openai('gpt-4o-mini') as any;

const { config, summary, warnings } = await loadAriaflowConfigWithResult({
  configPath: './ariaflow.jsonc',
  modelRegistry: {
    default: model,
    'openai:gpt-4o-mini': model
  }
});

console.log(`Loaded ${summary.agents} agents`);
```

### Create Runtime

```typescript
import { createRuntimeFromConfig } from '@ariaflowagents/config';

const { config } = await loadAriaflowConfigWithResult({
  configPath: './ariaflow.jsonc'
});

const runtime = createRuntimeFromConfig(config);
```

## Directory Structure

```
my-agent/
├── ariaflow.jsonc              # Main configuration
├── .ariaflow/
│   ├── prompts/
│   │   ├── system.md           # System prompts
│   │   ├── chat.md             # Agent prompts
│   │   └── triage.md           # Triage prompts
│   ├── tools/
│   │   ├── search/
│   │   │   ├── index.ts        # Tool implementation
│   │   │   └── tool.json       # Tool metadata
│   │   └── calculator/
│   │       ├── index.ts
│   │       └── tool.json
│   ├── skill/
│   │   └── my-skill/
│   │       └── SKILL.md
│   └── flow/
│       └── booking-flow.json   # Flow definitions
└── package.json                # Optional: Tool dependencies
```

## Example: Complete Configuration

```jsonc
{
  "$schema": "https://mithushancj.com/config.json",
  "name": "support-agent",
  "version": "1.0.0",
  "runtime": {
    "defaultAgent": "triage",
    "defaultModel": "gpt-4o-mini"
  },
  "models": {
    "default": "openai:gpt-4o-mini",
    "gpt-4": "openai:gpt-4"
  },
  "agents": {
    "triage": {
      "type": "triage",
      "description": "Routes support requests",
      "prompt": { "file": "./prompts/triage.md" },
      "routes": [
        { "agentId": "billing", "description": "Billing inquiries" },
        { "agentId": "technical", "description": "Technical support" }
      ],
      "defaultAgent": "billing"
    },
    "billing": {
      "type": "llm",
      "description": "Handles billing questions",
      "prompt": { "file": "./prompts/billing.md" },
      "tools": ["create_ticket"]
    },
    "technical": {
      "type": "llm",
      "description": "Technical support",
      "prompt": { "file": "./prompts/technical.md" },
      "tools": ["diagnose", "create_ticket"]
    }
  },
  "tools": {
    "create_ticket": {
      "type": "module",
      "entry": "./tools/create_ticket/index.ts"
    },
    "diagnose": {
      "type": "module",
      "entry": "./tools/diagnose/index.ts"
    }
  },
  "providers": {
    "openai": {
      "apiKey": "OPENAI_API_KEY"
    }
  }
}
```

## Configuration Reference

### Root Properties

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `$schema` | string | No | JSON schema URI |
| `name` | string | Yes | Agent name |
| `version` | string | No | Version number |
| `runtime` | object | Yes | Runtime configuration |
| `models` | object | Yes | Model registry |
| `agents` | object | Yes | Agent definitions |
| `flows` | object | No | Reusable flow definitions (`nodes` + `transitions`) |
| `tools` | object | No | Tool definitions |
| `providers` | object | No | Provider configurations |
| `permissions` | object | No | Permission settings |

### Runtime Properties

| Property | Type | Description |
|----------|------|-------------|
| `defaultAgent` | string | Default agent ID |
| `defaultModel` | string | Default model key |

### Agent Properties

| Property | Type | Description |
|----------|------|-------------|
| `type` | string | Agent type: `llm`, `triage`, `flow` |
| `description` | string | Agent description |
| `prompt` | object | Prompt configuration |
| `tools` | array | List of tool names |
| `routes` | array | Triage routes (triage only) |
| `defaultAgent` | string | Default route (triage only) |
| `flowRef` | string | Flow reference (flow only) |
| `mode` | string | Flow mode: `guided`, `hybrid` (flow only) |

### Flow Properties

| Property | Type | Description |
|----------|------|-------------|
| `entry` / `initialNode` | string | Initial node id |
| `defaultRolePrompt` | string | Global flow prompt applied to nodes by default |
| `nodes` | array | Flow nodes (`id`, `prompt`, optional `nodeType`, `addGlobalPrompt`) |
| `transitions` | array | Edges (`from`, `to`, `on`/`condition`, optional `contract`) |
| `contextStrategy` | string | `append`, `reset`, `reset_with_summary` |
| `summaryPrompt` | string | Prompt used when summarizing context |
| `summaryMaxTokens` | number | Max tokens for summary generation |
| `summaryTimeoutMs` | number | Summary timeout guardrail |
| `maxSteps` | number | Default max tool-call steps in stream loop |

### Prompt Properties

| Property | Type | Description |
|----------|------|-------------|
| `inline` | string | Inline prompt text |
| `file` | string | Path to prompt file |
| `template` | string | Built-in prompt template ID |
| `customize` | object | Template customization options |

### Troubleshooting Prompts

If you see warnings like `Agent "triage" is missing a prompt`, ensure the agent has a prompt defined via:

- `prompt.inline`
- `prompt.file`
- `prompt.template`

Missing prompts fall back to a placeholder and can lead to weak routing or off-topic responses.

## Best Practices

1. **Use file-based prompts** for complex prompts (>100 lines)
2. **Organize tools** in separate directories with `tool.json` metadata
3. **Use triage agents** for multi-agent routing
4. **Version your config** using semantic versioning
5. **Test locally** using the Hono server before deployment
6. **Use environment variables** for API keys

## Integration with Hono Server

```typescript
import { loadAriaflowConfigWithResult, createRuntimeFromConfig } from '@ariaflowagents/config';
import { createAriaChatRouter } from '@ariaflowagents/hono-server';

const { config, summary } = await loadAriaflowConfigWithResult({
  configPath: './ariaflow.jsonc',
  modelRegistry: { default: model }
});

const runtime = createRuntimeFromConfig(config);

const app = new Hono();
app.route('/', createAriaChatRouter({ runtime }));
```
