duel-agents-routing
CLI, SDK, and IDE plugins for Duel Agents - an LLM routing layer that runs prompts against multiple models and picks the cheapest winning answer
How do I install this agent skill?
npx skills add https://github.com/reason-machines/ai-agent-skills --skill duel-agents-routingIs this agent skill safe to install?
- Gen Agent Trust Hubwarn
This skill facilitates LLM request routing through a third-party service, requiring the installation of packages from an unverified npm scope and cloning code from a personal GitHub repository. It routes all prompt and response data through an external domain, creating potential privacy risks and an attack surface for indirect prompt injection.
- Socketwarn
1 alert: gptAnomaly
- Snykfail
Risk: HIGH · 1 issue
What does this agent skill do?
Duel Agents Routing
Skill by ara.so — AI Agent Skills collection.
Overview
Duel Agents is an IDE-native routing layer that runs prompts against multiple LLM models simultaneously and selects the cheapest answer that meets quality thresholds. It provides:
- Automatic model selection via
duel-automodel name - Cost optimization by choosing cheaper models when quality is sufficient
- OpenAI-compatible and Anthropic-compatible APIs
- IDE integrations for Claude Code, Cursor, Codex, and OpenClaw
- TypeScript SDK for building custom agents and applications
The service routes traffic through https://duelagents.com/v1 using Duel API keys (duel_<prefix>_<secret>).
Prerequisites
You must have a Duel API key. Raw Anthropic or OpenAI keys will not work.
- Subscribe at https://duelagents.com/dashboard/settings
- Create an API key from the dashboard
- Key format:
duel_+ 8 characters +_+ 32 characters
Installation
Quick Start (All Tools)
# Set your API key
export DUEL_API_KEY=duel_yourprefix_yoursecret
# Install for all supported tools
npx @duel-agents/install all
# Verify installation
npx @duel-agents/install doctor
Per-Tool Installation
# Claude Code
npx @duel-agents/install claude-code
# Cursor IDE
npx @duel-agents/install cursor
# Codex CLI
npx @duel-agents/install codex
# OpenClaw
npx @duel-agents/install openclaw
SDK for Custom Applications
npm install @duel-agents/sdk
Configuration
Environment Variables
| Variable | Required | Purpose |
|---|---|---|
DUEL_API_KEY | Yes | Your Duel API key from the dashboard |
DUEL_AGENTS_API_KEY | No | Alias for DUEL_API_KEY |
DUEL_PROXY_URL | No | Override proxy URL (staging environments only) |
OPENCLAW_CONFIG_PATH | No | Custom OpenClaw config file path |
Setting Environment Variables
.env file:
DUEL_API_KEY=duel_abc12345_def67890ghijklmnopqrstuvwxyz12
Shell export:
export DUEL_API_KEY=duel_abc12345_def67890ghijklmnopqrstuvwxyz12
SDK Usage
OpenAI-Compatible API
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!, // required
});
// Chat completions
const response = await duel.chat.completions.create({
model: "duel-auto", // automatic model selection
messages: [
{ role: "system", content: "You are a helpful coding assistant." },
{ role: "user", content: "Explain TypeScript generics briefly." }
],
temperature: 0.7,
max_tokens: 500,
});
console.log(response.choices[0].message.content);
Anthropic-Compatible API
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
const message = await duel.messages.create({
model: "duel-auto",
max_tokens: 1024,
messages: [
{ role: "user", content: "Write a Python function to parse JSON safely." }
],
});
console.log(message.content);
Streaming Responses
const stream = await duel.chat.completions.create({
model: "duel-auto",
messages: [{ role: "user", content: "Count to 10" }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices[0]?.delta?.content;
if (content) {
process.stdout.write(content);
}
}
Error Handling
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
try {
const response = await duel.chat.completions.create({
model: "duel-auto",
messages: [{ role: "user", content: "Hello" }],
});
} catch (error) {
if (error.status === 401) {
console.error("Invalid API key or subscription inactive");
} else if (error.status === 429) {
console.error("Rate limit exceeded");
} else {
console.error("Request failed:", error.message);
}
}
IDE Integrations
Claude Code
# Clone repo and install plugin
git clone https://github.com/2aronS/Duel-Agents.git
cd duel-agents
claude plugin install ./integrations/claude-plugin
# Run installer
npx @duel-agents/install claude-code
In Claude Code:
/duel-agents:setup
Follow the guided setup to configure your API key and preferences.
Cursor
The installer copies a skill to .cursor/skills/duel-agents/ and writes DUEL_API_KEY to your project .env.
Manual configuration required:
- Open Cursor Settings → Models
- Set Override OpenAI Base URL to:
https://duelagents.com/v1 - Set API Key to your Duel key:
duel_yourprefix_yoursecret - Select
duel-autoas your model
npx @duel-agents/install cursor
Codex CLI
The installer writes OPENAI_BASE_URL and OPENAI_API_KEY to .env:
npx @duel-agents/install codex
# Restart Codex after installation
OpenClaw
Patches ~/.openclaw/openclaw.json with a duel provider and sets the default model:
npx @duel-agents/install openclaw
# Validate configuration
openclaw config validate
Manual configuration (~/.openclaw/openclaw.json):
{
"providers": {
"duel": {
"apiKey": "duel_yourprefix_yoursecret",
"baseURL": "https://duelagents.com/v1"
}
},
"defaultModel": "duel/duel-auto"
}
A backup is created at openclaw.json.bak before patching.
CLI Commands
Install Command
# Install for specific tool
npx @duel-agents/install <tool>
# Available tools:
# - claude-code
# - cursor
# - codex
# - openclaw
# - all
Doctor Command
Validates your setup and connectivity:
npx @duel-agents/install doctor
Checks:
- API key format validity
- Connectivity to
duelagents.com/v1 - Subscription status
- Environment variable configuration
Common Patterns
Multi-Agent System
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
async function coordinatedAgents(task: string) {
// Planner agent
const plan = await duel.chat.completions.create({
model: "duel-auto",
messages: [
{ role: "system", content: "You are a task planning agent." },
{ role: "user", content: `Create a plan for: ${task}` }
],
});
const steps = plan.choices[0].message.content;
// Executor agent
const execution = await duel.chat.completions.create({
model: "duel-auto",
messages: [
{ role: "system", content: "You are a task execution agent." },
{ role: "user", content: `Execute this plan:\n${steps}` }
],
});
return execution.choices[0].message.content;
}
Cost-Aware Routing
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
async function analyzeCode(code: string, complexity: "simple" | "complex") {
// Duel automatically routes to cheaper models for simple tasks
const response = await duel.chat.completions.create({
model: "duel-auto",
messages: [
{
role: "user",
content: `Analyze this ${complexity} code:\n\n${code}`
}
],
// Duel uses prompt complexity to select optimal model
});
return response.choices[0].message.content;
}
Use with Existing OpenAI Code
Replace only the client initialization:
// Before:
// import OpenAI from "openai";
// const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
// After:
import { DuelClient } from "@duel-agents/sdk";
const client = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
// All existing OpenAI code works unchanged
const response = await client.chat.completions.create({
model: "duel-auto", // or keep your existing model name
messages: [{ role: "user", content: "Hello" }],
});
Fallback Strategy
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
});
async function robustCompletion(prompt: string) {
try {
// Try Duel routing first (cost-optimized)
return await duel.chat.completions.create({
model: "duel-auto",
messages: [{ role: "user", content: prompt }],
});
} catch (error) {
console.warn("Duel routing failed, using direct fallback");
// Fallback logic here if needed
throw error;
}
}
Troubleshooting
Invalid API Key Format
Symptom: Invalid API key format error
Solution:
- Key must match pattern:
duel_+ 8 chars +_+ 32 chars - Create a new key at https://duelagents.com/dashboard/settings
- Verify no extra whitespace:
echo "$DUEL_API_KEY" | wc -cshould be 46
401 Unauthorized
Symptom: 401 error when running doctor or making requests
Solution:
- Key may be revoked or subscription inactive
- Check billing status at dashboard
- Generate a new API key
- Ensure key is exported:
echo $DUEL_API_KEY
Could Not Reach Duel API
Symptom: Connection errors to duelagents.com/v1
Solution:
- Verify internet connectivity
- Check if
duelagents.comis accessible:curl https://duelagents.com/v1/health - Proxy may be temporarily down; retry after a few minutes
- Check for firewall or VPN restrictions
Cursor Still Uses OpenAI
Symptom: Cursor not routing through Duel
Solution:
- Open Settings → Models → Override OpenAI Base URL
- Set to:
https://duelagents.com/v1 - Set API key field to your
duel_*key (not OpenAI key) - Restart Cursor
- Select
duel-autoorduel/duel-autoas model
OpenClaw Won't Start
Symptom: OpenClaw fails after Duel installation
Solution:
# Validate configuration
openclaw config validate
# Restore from backup if needed
cp ~/.openclaw/openclaw.json.bak ~/.openclaw/openclaw.json
# Reinstall
npx @duel-agents/install openclaw
Skill Copy Failed
Symptom: Cursor skill not found after npm install
Solution:
# Rebuild the package
git clone https://github.com/2aronS/Duel-Agents.git
cd duel-agents
npm install
npm run build
# Reinstall
npx @duel-agents/install cursor
TypeScript Type Errors
Symptom: TypeScript errors with SDK
Solution:
# Ensure latest version
npm install @duel-agents/sdk@latest
# Check TypeScript version (>= 4.5 recommended)
npm list typescript
Model Selection
Available Models
duel-auto- Automatic routing (recommended)- Any OpenAI model name (routed through Duel)
- Any Anthropic model name (routed through Duel)
How Auto-Routing Works
Duel analyzes:
- Prompt complexity
- Required capabilities (code, reasoning, creative)
- Token length
- Historical quality metrics
Then selects the cheapest model that meets the quality threshold for that specific request.
Advanced Configuration
Custom Base URL (Staging)
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
baseURL: process.env.DUEL_PROXY_URL || "https://duelagents.com/v1",
});
Timeout Configuration
import { DuelClient } from "@duel-agents/sdk";
const duel = new DuelClient({
apiKey: process.env.DUEL_API_KEY!,
timeout: 60000, // 60 seconds
});
Repository Structure
packages/
core/ @duel-agents/core - Validation, env handling, connectivity
cli/ @duel-agents/install - Installer CLI tool
sdk/ @duel-agents/sdk - TypeScript API client
integrations/
claude-plugin/ - Claude Code plugin
cursor-skill/ - Cursor IDE skill
openclaw-skill/ - OpenClaw integration
templates/
cursor-models.override.md - Cursor configuration example
openclaw.duel.json5 - OpenClaw configuration example
Development
# Clone repository
git clone https://github.com/2aronS/Duel-Agents.git
cd duel-agents
# Install dependencies
npm install
# Build all packages
npm run build
# Run tests
npm test
# Run installer locally
npm run cli -- install doctor
License
MIT License - see repository for full text.
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/reason-machines/ai-agent-skills/duel-agents-routing">View duel-agents-routing on skillZs</a>