Execution Proxy
SkillRouter acts as an intelligent proxy between your AI agents and third-party APIs, handling authentication, retries, timeouts, and browser orchestration so your agents can focus on reasoning.
How SkillRouter Proxies Execution
When your agent calls sr.execute(), the request never goes directly to the third-party API. Instead, SkillRouter receives the request, validates the input against the skill schema, attaches the appropriate credentials, and forwards it to the target service. The response is then normalized into a consistent format before being returned to your agent.
This proxy architecture provides several advantages: your agent code never handles raw API keys, all executions are logged and metered, and SkillRouter can transparently retry failed requests or switch to fallback providers.
import SkillRouter from '@skillrouter/sdk';
const sr = new SkillRouter({ apiKey: process.env.SR_API_KEY });
// Your agent simply calls execute — SkillRouter handles the rest
const result = await sr.execute("stripe-create-checkout", {
amount: 2999,
currency: "usd",
customer_email: "buyer@example.com",
success_url: "https://myapp.com/success",
});
console.log(result.status); // "success"
console.log(result.data); // { session_id: "cs_live_...", url: "https://..." }Authentication Forwarding
SkillRouter manages credentials for third-party APIs on your behalf. When you connect a provider through the dashboard, SkillRouter securely stores your API keys, OAuth tokens, or service account credentials in an encrypted vault. During execution, the correct credentials are injected into the outgoing request automatically.
API Key Injection
Keys are injected at the proxy layer and never exposed to agent code or logs.
OAuth Token Refresh
Expired OAuth tokens are automatically refreshed before forwarding the request.
// Connect credentials once via the dashboard or SDK
await sr.credentials.connect("github", {
type: "oauth",
access_token: "gho_xxxxxxxxxxxx",
refresh_token: "ghr_xxxxxxxxxxxx",
});
// Subsequent executions use the stored credentials automatically
const repos = await sr.execute("github-list-repos", {
org: "my-org",
sort: "updated",
});Automatic Retries & Error Handling
SkillRouter implements intelligent retry logic for transient failures. By default, failed requests are retried up to 3 times with exponential backoff. Only retryable errors (network timeouts, 429 rate limits, 502/503/504 gateway errors) trigger retries. Client errors like 400 or 401 are returned immediately.
// Customize retry behavior per execution
const result = await sr.execute("sendgrid-send-email", {
to: "user@example.com",
subject: "Invoice #1234",
html: "<p>Your invoice is attached.</p>",
}, {
retries: 5, // max retry attempts
backoff: "exponential", // "exponential" | "linear" | "fixed"
backoff_base_ms: 500, // initial delay between retries
retry_on: [429, 502, 503], // specific status codes to retry
});When all retries are exhausted, SkillRouter returns a structured error response that your agent can reason about:
{
"status": "error",
"error": {
"code": "UPSTREAM_UNAVAILABLE",
"message": "SendGrid API returned 503 after 3 retries",
"retries_attempted": 3,
"last_status_code": 503,
"suggestion": "Try again later or use an alternative email provider"
}
}Timeout Configuration
Every skill execution has a default timeout of 30 seconds, which can be overridden at the call site. For long-running skills like web scraping or file processing, you can extend the timeout up to 5 minutes. If a request exceeds its timeout, SkillRouter cancels the upstream request and returns a timeout error.
// Set a custom timeout for a long-running skill
const result = await sr.execute("web-scrape-page", {
url: "https://example.com/large-dataset",
extract: ["tables", "links"],
}, {
timeout_ms: 120000, // 2 minutes
});
// Set a global default timeout for all executions
const sr = new SkillRouter({
apiKey: process.env.SR_API_KEY,
defaults: {
timeout_ms: 45000, // 45 seconds
retries: 2,
},
});| Skill Type | Default Timeout | Max Timeout |
|---|---|---|
| API Skills | 30s | 120s |
| Web Browsing Skills | 60s | 300s |
| File Processing Skills | 45s | 300s |
| Database Skills | 15s | 60s |
Browser Instance Management
Some skills interact with websites that require a real browser environment — filling out forms, navigating SPAs, or extracting dynamically rendered content. For these web skills, SkillRouter manages a pool of headless browser instances that are allocated on demand.
Pooled Browsers
Warm browser instances are reused across executions to eliminate cold-start latency.
Isolated Contexts
Each execution gets a fresh browser context with isolated cookies, storage, and network state.
// Web skills automatically use managed browser instances
const result = await sr.execute("web-fill-form", {
url: "https://app.example.com/signup",
fields: {
"#email": "user@example.com",
"#company": "Acme Corp",
},
submit_selector: "button[type=submit]",
wait_for: ".success-message",
}, {
timeout_ms: 90000, // web skills may need more time
browser: {
viewport: { width: 1280, height: 720 },
user_agent: "SkillRouter/1.0",
},
});Execution Lifecycle
Every skill execution passes through a well-defined lifecycle. Understanding these stages helps you debug issues and configure appropriate timeouts.
Validation
Input parameters are validated against the skill's JSON Schema. Invalid requests are rejected immediately with a descriptive error.
Authentication
Stored credentials are retrieved from the vault. OAuth tokens are refreshed if expired. API keys are injected into request headers.
Execution
The request is forwarded to the upstream API or a browser instance is allocated for web skills. The timeout clock starts.
Retry (if needed)
Transient failures trigger automatic retries with exponential backoff. Non-retryable errors skip this stage.
Normalization
The upstream response is transformed into SkillRouter's standard response format with consistent status, data, and metadata fields.
Response
The normalized result is returned to your agent along with execution metadata (duration, retries used, provider).