Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ author: gitagent-examples
license: MIT

model:
preferred: claude-sonnet-4-5-20250929
preferred: anthropic:claude-sonnet-4-5-20250929
fallback:
- claude-haiku-4-5-20251001
- anthropic:claude-haiku-4-5-20251001
constraints:
temperature: 0.2
max_tokens: 4096
Expand Down Expand Up @@ -213,9 +213,9 @@ author: Acme Corp
license: MIT

model:
preferred: claude-opus-4-6
preferred: anthropic:claude-opus-4-6
fallback:
- claude-sonnet-4-5-20250929
- anthropic:claude-sonnet-4-5-20250929
constraints:
temperature: 0.2
max_tokens: 4096
Expand Down
4 changes: 2 additions & 2 deletions examples/full/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: Financial compliance analysis agent for FINRA and Federal Reserve r
author: gitagent-examples
license: proprietary
model:
preferred: claude-opus-4-6
preferred: anthropic:claude-opus-4-6
fallback:
- claude-sonnet-4-5-20250929
- anthropic:claude-sonnet-4-5-20250929
constraints:
temperature: 0.1
max_tokens: 8192
Expand Down
2 changes: 1 addition & 1 deletion examples/full/tools/generate-report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ output_schema:
description: Path to saved report file
implementation:
type: script
path: generate-report.sh
script: generate-report.sh
runtime: bash
timeout: 60
annotations:
Expand Down
2 changes: 1 addition & 1 deletion examples/full/tools/search-regulations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ output_schema:
type: integer
implementation:
type: script
path: search-regulations.py
script: search-regulations.py
runtime: python3
timeout: 30
annotations:
Expand Down
4 changes: 2 additions & 2 deletions examples/gitagent-helper/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: Your AI assistant for building, running, and managing git-native AI
author: gitagent
license: MIT
model:
preferred: claude-sonnet-4-5-20250929
preferred: anthropic:claude-sonnet-4-5-20250929
fallback:
- claude-haiku-4-5-20251001
- anthropic:claude-haiku-4-5-20251001
constraints:
temperature: 0.2
max_tokens: 8192
Expand Down
4 changes: 2 additions & 2 deletions examples/jason-my-claw-is-the-law-deebee-4567b4/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ author: bengii
license: MIT

model:
preferred: ollama/qwen3-coder:latest
preferred: ollama:qwen3-coder:latest
fallback:
- cerebras/qwen-3-235b-a22b-instruct-2507
- cerebras:qwen-3-235b-a22b-instruct-2507
constraints:
temperature: 0.3
max_tokens: 4096
Expand Down
4 changes: 2 additions & 2 deletions examples/llm-wiki/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: "LLM-maintained personal wiki — a persistent, compounding knowled
author: gitagent-examples
license: MIT
model:
preferred: claude-sonnet-4-5-20250929
preferred: anthropic:claude-sonnet-4-5-20250929
fallback:
- claude-haiku-4-5-20251001
- anthropic:claude-haiku-4-5-20251001
skills:
- wiki-ingest
- wiki-query
Expand Down
4 changes: 2 additions & 2 deletions examples/lyzr-agent/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: AI research assistant that summarizes topics, answers questions, an
author: gitagent-examples
license: MIT
model:
preferred: gpt-4.1
preferred: openai:gpt-4.1
fallback:
- gpt-4.1-mini
- openai:gpt-4.1-mini
constraints:
temperature: 0.3
max_tokens: 4096
Expand Down
4 changes: 2 additions & 2 deletions examples/nvidia-deep-researcher/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ description: >
structured TOC, and verified sources using a coordinated orchestrator-planner-researcher hierarchy.

model:
preferred: openai/gpt-oss-120b
preferred: openai:gpt-oss-120b
fallback:
- nvidia/nemotron-3-super-120b-a12b
- nvidia:nemotron-3-super-120b-a12b
constraints:
temperature: 0.2
max_tokens: 16384
Expand Down
4 changes: 2 additions & 2 deletions examples/standard/agent.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: Automated code review agent with best-practice enforcement
author: gitagent-examples
license: MIT
model:
preferred: claude-sonnet-4-5-20250929
preferred: anthropic:claude-sonnet-4-5-20250929
fallback:
- claude-haiku-4-5-20251001
- anthropic:claude-haiku-4-5-20251001
constraints:
temperature: 0.2
max_tokens: 4096
Expand Down
2 changes: 1 addition & 1 deletion examples/standard/tools/complexity-analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ output_schema:
exceeds_threshold: { type: boolean }
implementation:
type: script
path: complexity-analysis.sh
script: complexity-analysis.sh
runtime: bash
timeout: 30
annotations:
Expand Down
2 changes: 1 addition & 1 deletion examples/standard/tools/lint-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ output_schema:
rule: { type: string }
implementation:
type: script
path: lint-check.sh
script: lint-check.sh
runtime: bash
timeout: 30
annotations:
Expand Down
10 changes: 5 additions & 5 deletions spec/SPECIFICATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ All YAML keys use **snake_case**. Agent names, skill names, and tool names use *
| `author` | string | Author name or organization |
| `license` | string | SPDX license identifier |
| `model` | object | Model preferences (see Model section) |
| `model.preferred` | string | Primary model ID (e.g., `claude-opus-4-6`, `gpt-4o`) |
| `model.preferred` | string | Primary model ID (e.g., `anthropic:claude-opus-4-6`, `openai:gpt-4o`) |
| `model.fallback` | string[] | Fallback model IDs in priority order |
| `model.constraints` | object | Parameters: `temperature`, `max_tokens`, `top_p`, `top_k`, `stop_sequences`, `presence_penalty`, `frequency_penalty` |
| `extends` | string | Parent agent (git URL or local path) |
Expand Down Expand Up @@ -279,9 +279,9 @@ description: Financial compliance analysis agent
author: Acme Financial
license: proprietary
model:
preferred: claude-opus-4-6
preferred: anthropic:claude-opus-4-6
fallback:
- claude-sonnet-4-5-20250929
- anthropic:claude-sonnet-4-5-20250929
constraints:
temperature: 0.1
max_tokens: 8192
Expand Down Expand Up @@ -606,7 +606,7 @@ output_schema:
url: { type: string }
implementation:
type: script
path: search-regulations.py
script: search-regulations.py
runtime: python3
timeout: 30
annotations:
Expand Down Expand Up @@ -775,7 +775,7 @@ agents/
name: fact-checker
description: Verifies claims against authoritative sources
model:
preferred: claude-haiku-4-5-20251001
preferred: anthropic:claude-haiku-4-5-20251001
delegation:
mode: auto
triggers:
Expand Down
7 changes: 4 additions & 3 deletions spec/schemas/agent-yaml.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@
"properties": {
"preferred": {
"type": "string",
"description": "Primary model ID (e.g., claude-opus-4-6, gpt-4o)"
"pattern": "^[a-z0-9-]+:.+$",
"description": "Primary model in canonical 'provider:model' form (e.g., anthropic:claude-opus-4-8, openai:gpt-4o)"
},
"fallback": {
"type": "array",
"items": { "type": "string" },
"description": "Fallback model IDs in priority order"
"items": { "type": "string", "pattern": "^[a-z0-9-]+:.+$" },
"description": "Fallback models in canonical 'provider:model' form, priority order"
},
"constraints": {
"type": "object",
Expand Down
14 changes: 12 additions & 2 deletions spec/schemas/tool.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,13 @@
"enum": ["script", "mcp_server", "http"],
"description": "'script': local executable. 'mcp_server': MCP server tool. 'http': REST API endpoint."
},
"script": {
"type": "string",
"description": "Path to implementation script (relative to tools/). Preferred field for type: script."
},
"path": {
"type": "string",
"description": "Path to implementation script (relative to tools/)"
"description": "DEPRECATED alias for 'script'. Use 'script' instead — some runtimes (e.g. gitagent) only read 'script'."
},
"runtime": {
"type": "string",
Expand Down Expand Up @@ -96,7 +100,13 @@
"allOf": [
{
"if": { "properties": { "type": { "const": "script" } } },
"then": { "required": ["path", "runtime"] }
"then": {
"required": ["runtime"],
"anyOf": [
{ "required": ["script"] },
{ "required": ["path"] }
]
}
},
{
"if": { "properties": { "type": { "const": "http" } } },
Expand Down
30 changes: 7 additions & 23 deletions src/adapters/codex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { join, resolve } from 'node:path';
import yaml from 'js-yaml';
import { loadAgentManifest, loadFileIfExists } from '../utils/loader.js';
import { loadAllSkills, getAllowedTools } from '../utils/skill-loader.js';
import { parseModel } from '../utils/model.js';
import { buildComplianceSection, buildMcpServersConfig } from './shared.js';

/**
Expand Down Expand Up @@ -171,17 +172,13 @@ function buildInstructions(
function buildConfig(manifest: ReturnType<typeof loadAgentManifest>): Record<string, unknown> {
const config: Record<string, unknown> = {};

// Map model preference to Codex CLI model format
// Codex CLI config.json accepts: { model: "string", provider?: "openai|azure|..." }
// Canonical "provider:model" → Codex CLI { model, provider? }
// Codex defaults to openai; any non-openai provider is reached via its openai-compatible endpoint.
if (manifest.model?.preferred) {
const model = manifest.model.preferred;
config.model = model;

// Add provider hint when it can be inferred from the model name
const provider = inferProvider(model);
if (provider !== 'openai') {
// Only emit provider when non-default — Codex defaults to openai
config.provider = provider;
const { provider, modelId } = parseModel(manifest.model.preferred);
config.model = modelId;
if (provider !== 'openai' && provider !== 'openai-codex') {
config.provider = 'openai-compatible';
}
}

Expand All @@ -194,16 +191,3 @@ function buildConfig(manifest: ReturnType<typeof loadAgentManifest>): Record<str
return config;
}

/**
* Infer the Codex CLI provider name from a model identifier.
* Codex CLI providers: openai (default), azure, ollama, openai-compatible
*/
function inferProvider(model: string): string {
if (model.startsWith('claude') || model.includes('anthropic')) return 'openai-compatible';
if (model.startsWith('gemini') || model.includes('google')) return 'openai-compatible';
if (model.startsWith('deepseek')) return 'openai-compatible';
if (model.startsWith('llama') || model.startsWith('mistral') || model.startsWith('qwen')) return 'ollama';
if (model.startsWith('o1') || model.startsWith('o3') || model.startsWith('o4') || model.startsWith('gpt')) return 'openai';
if (model.startsWith('codex')) return 'openai';
return 'openai';
}
10 changes: 4 additions & 6 deletions src/adapters/gemini.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { join, resolve } from 'node:path';
import yaml from 'js-yaml';
import { loadAgentManifest, loadFileIfExists } from '../utils/loader.js';
import { loadAllSkills, getAllowedTools } from '../utils/skill-loader.js';
import { parseModel } from '../utils/model.js';
import { buildComplianceSection, buildMcpServersConfig } from './shared.js';

/**
Expand Down Expand Up @@ -197,14 +198,11 @@ function buildSettings(
const settings: Record<string, unknown> = {};

// Model preference - Gemini CLI expects object format
// Canonical "provider:model" → { id: model, provider }
if (manifest.model?.preferred) {
// Extract provider from model name or default to google
const modelName = manifest.model.preferred;
const provider = modelName.includes('claude') ? 'anthropic' :
modelName.includes('gpt') ? 'openai' : 'google';

const { provider, modelId } = parseModel(manifest.model.preferred);
settings.model = {
id: modelName,
id: modelId,
provider: provider
};
}
Expand Down
25 changes: 7 additions & 18 deletions src/adapters/gitclaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { join, resolve } from 'node:path';
import yaml from 'js-yaml';
import { loadAgentManifest, loadFileIfExists } from '../utils/loader.js';
import { loadAllSkills } from '../utils/skill-loader.js';
import { parseModel } from '../utils/model.js';

/**
* Export a gitagent to gitclaw format.
Expand Down Expand Up @@ -152,26 +153,14 @@ function buildAgentYaml(
}

/**
* Convert gitagent model name to gitclaw "provider:model-id" format.
* gitagent: "claude-sonnet-4-5" or "anthropic/claude-sonnet-4-5"
* gitclaw: "anthropic:claude-sonnet-4-5"
* Normalize the canonical "provider:model" source into gitclaw "provider:model-id" form.
* Both use the same colon convention, so this validates and re-emits the value.
* source: "anthropic:claude-sonnet-4-5"
* gitclaw: "anthropic:claude-sonnet-4-5"
*/
function toGitclawModel(model: string): string {
// Already in provider:model format
if (model.includes(':') && !model.includes('://')) return model;

// provider/model → provider:model
if (model.includes('/')) {
return model.replace('/', ':');
}

// Infer provider from model name
if (model.startsWith('claude') || model.includes('anthropic')) return `anthropic:${model}`;
if (model.startsWith('gpt') || model.startsWith('o1') || model.startsWith('o3') || model.startsWith('o4')) return `openai:${model}`;
if (model.startsWith('gemini')) return `google:${model}`;
if (model.startsWith('deepseek')) return `deepseek:${model}`;
if (model.startsWith('llama') || model.startsWith('mistral')) return `ollama:${model}`;
return `openai:${model}`;
const { provider, modelId } = parseModel(model);
return `${provider}:${modelId}`;
}

function collectToolNames(agentDir: string): string[] {
Expand Down
16 changes: 4 additions & 12 deletions src/adapters/github.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { resolve, join } from 'node:path';
import { loadAgentManifest } from '../utils/loader.js';
import { parseModel } from '../utils/model.js';
import { exportToSystemPrompt } from './system-prompt.js';

export interface GitHubModelsPayload {
Expand All @@ -14,19 +15,10 @@ export interface GitHubModelsPayload {
* Map an agent.yaml model to a GitHub Models model ID (vendor/model).
*/
function resolveModel(model?: string): string {
// Canonical "provider:model" → GitHub Models "provider/model" form.
if (!model) return 'openai/gpt-4.1';
if (model.includes('/')) return model;

if (model.startsWith('gpt') || model.startsWith('o1') || model.startsWith('o3') || model.startsWith('o4')) {
return `openai/${model}`;
}
if (model.startsWith('claude')) return `anthropic/${model}`;
if (model.startsWith('llama') || model.startsWith('Llama')) return `meta/${model}`;
if (model.startsWith('mistral') || model.startsWith('Mistral')) return `mistralai/${model}`;
if (model.startsWith('gemini')) return `google/${model}`;
if (model.startsWith('deepseek') || model.startsWith('DeepSeek')) return `deepseek/${model}`;

return model;
const { provider, modelId } = parseModel(model);
return `${provider}/${modelId}`;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/adapters/kiro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { join, resolve } from 'node:path';
import yaml from 'js-yaml';
import { loadAgentManifest, loadFileIfExists } from '../utils/loader.js';
import { loadAllSkills, getAllowedTools } from '../utils/skill-loader.js';
import { parseModel } from '../utils/model.js';
import { buildComplianceSection } from './shared.js';

/**
Expand Down Expand Up @@ -168,7 +169,7 @@ function buildConfig(
config.prompt = 'file://./prompt.md';

if (manifest.model?.preferred) {
config.model = manifest.model.preferred;
config.model = parseModel(manifest.model.preferred).modelId;
}

// Collect tools from skills and tool definitions
Expand Down
Loading