Discover, parse, and call external HTTP APIs at runtime using OpenAPI specs, tool templates, and iterative chaining. Adapted from UTCP (Universal Tool Calling Protocol) patterns for Node.js and Claude Code agents.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Discover, parse, and call external HTTP APIs at runtime using OpenAPI specs, tool templates, and iterative chaining. Adapted from UTCP (Universal Tool Calling Protocol) patterns for Node.js and Claude Code agents.
["Always fetch and validate the OpenAPI spec before constructing requests","Use environment variables for all API keys and secrets; never hardcode","Apply max_iterations guard to prevent infinite API call loops","Truncate or summarize large API responses to stay within context budget","Match user intent to API endpoints semantically before calling","Handle errors explicitly with retry logic for transient failures"]
error_handling
strict
streaming
supported
source
builtin
trust_score
100
provenance_sha
ef94e12361c4dee5
Mode: Cognitive/Prompt-Driven — No standalone utility script; use via agent context.
Dynamic API Integration
Overview
This skill teaches agents how to dynamically discover, parse, and call external HTTP APIs at runtime. It is adapted from the Universal Tool Calling Protocol (UTCP) patterns, translated into Node.js / Claude Code tool patterns.
Core workflow (5-phase, inspired by UTCP agent state machine):
Discover — Fetch and parse an OpenAPI/Swagger spec (or define a manual tool template).
Match — Map the user's intent to the right API endpoint semantically.
Construct — Build the HTTP request with proper method, path, params, headers, body, and auth.
Execute — Call the API via Bash (curl) or WebFetch and capture the response.
Chain — If the task is not yet complete, re-analyze and execute another call (up to max_iterations).
When to Use
Use this skill when:
Agent needs to call an external REST API it has not used before
User provides an API URL or OpenAPI spec URL and wants data extracted
Agent must discover available endpoints from a spec before choosing which to call
Multiple API calls need to be chained iteratively (search -> get details -> filter)
Agent needs to construct HTTP requests with authentication and parameters
Do NOT use when:
The API is already wrapped as an MCP tool (use the MCP tool directly)
The integration is a one-time hardcoded call (just use Bash curl directly)
The API requires OAuth 2.0 authorization code flow with user-interactive redirect
The API uses WebSocket or streaming-only protocols (not HTTP REST)
Iron Laws
NEVER hardcode API keys, tokens, or secrets in requests, curl commands, or source files — always use environment variables ($ENV_VAR) or a secrets manager.
ALWAYS discover the API spec (OpenAPI/Swagger) before writing any integration code — guessing endpoint shapes without spec evidence produces broken integrations.
NEVER skip pagination handling when the API returns list responses — assuming single-page results silently drops data for any dataset above the page limit.
ALWAYS implement retry logic with exponential backoff for transient failures (429, 503) — dynamic APIs are unreliable by nature and integrations without retries fail under normal production conditions.
NEVER trust API responses without validating the schema of each response before use — dynamic API shapes change without notice; unvalidated responses cause runtime crashes in callers.
Phase 1: Discover — Fetch and Parse the API Spec
Option A: OpenAPI/Swagger Spec Discovery
When the API provides an OpenAPI spec (most modern APIs do):
# Step 1: Fetch the OpenAPI spec
WebFetch({
url: "https://api.example.com/openapi.json",
prompt: "Extract all API endpoints. For each endpoint, list: HTTP method, path, description, required parameters, optional parameters, authentication requirement. Return as a structured list."
})
What to extract from the spec:
Field
Location in Spec
Purpose
Base URL
servers[0].url
API root for all requests
Endpoints
paths.*
Available operations
Methods
paths.*.get/post/put/delete
HTTP verbs per endpoint
Parameters
paths.*.*.parameters[]
Query, path, header params
Request body
paths.*.*.requestBody
POST/PUT payload schema
Auth
components.securitySchemes
API key, Bearer, OAuth
Response schema
paths.*.*.responses.200
Expected response format
Common OpenAPI spec locations:
https://api.example.com/openapi.json
https://api.example.com/swagger.json
https://api.example.com/v3/api-docs
https://api.example.com/.well-known/openapi.json
https://api.example.com/docs (HTML page may link to spec)
Option B: Manual Tool Template (No Spec Available)
When no OpenAPI spec exists, define a tool template manually:
{"name":"search_books","description":"Search Open Library for books by query","base_url":"https://openlibrary.org/search.json","method":"GET","auth":null,"parameters":{"q":{"type":"string","required":true,"in":"query","description":"Search query (title, author, ISBN)"},"limit":{"type":"integer","required":false,"in":"query","description":"Max results to return (default 10)"},"page":{"type":"integer","required":false,"in":"query","description":"Page number for pagination"}},"response_hint":"Returns { numFound, docs: [{ title, author_name, first_publish_year }] }"}
Tool Template JSON Schema
The tool template format (inspired by UTCP manual_call_templates):
{"name":"string (required) — unique tool identifier, lowercase_snake_case","description":"string (required) — what this tool does, used for semantic matching","base_url":"string (required) — full URL including path","method":"string (required) — GET | POST | PUT | PATCH | DELETE","content_type":"string (optional) — default: application/json","auth":{"type":"string — api_key | bearer | basic | none","header":"string — header name (e.g., X-Api-Key, Authorization)","env_var":"string — environment variable name holding the secret","prefix":"string (optional) — e.g., 'Bearer ' for bearer auth"},"parameters":{"<param_name>":{"type":"string | integer | boolean | array | object","required":"boolean","in":"query | path | header | body","description":"string — what this parameter does","default":"any (optional) — default value if not provided"}},"response_hint":"string (optional) — brief description of response shape"}
Phase 2: Match — Semantic Intent-to-Endpoint Mapping
Before calling an API, match the user's intent to the correct endpoint:
Step 1: Understand the user's goal
Ask yourself: What data does the user want? What action do they want performed?
Step 2: Map intent to endpoint
User Intent
Likely HTTP Method
Endpoint Pattern
"Find / search / list / get"
GET
/search, /list, /{resource}
"Create / add / register"
POST
/{resource}
"Update / modify / change"
PUT or PATCH
/{resource}/{id}
"Delete / remove"
DELETE
/{resource}/{id}
"Get details about X"
GET
/{resource}/{id}
Step 3: Select parameters
Required parameters: Must be provided (check required: true in spec/template).
Optional parameters: Use only if user specified them or they improve results.
Path parameters: Substitute into URL (e.g., /repos/{owner}/{repo}).
Query parameters: Append as ?key=value&key2=value2.
Body parameters: Send as JSON payload in POST/PUT/PATCH.
Phase 3: Construct — Build the HTTP Request
Request Construction Checklist
URL: Base URL + path + path parameter substitution
Phase 4: Execute — Call the API and Process the Response
Using Bash (curl) — Primary Method
# Execute and capture response + HTTP status
RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "https://api.example.com/search?q=test" \
-H "Accept: application/json")
HTTP_CODE=$(echo"$RESPONSE" | tail -1)
BODY=$(echo"$RESPONSE" | sed '$d')
echo"Status: $HTTP_CODE"echo"Body: $BODY" | head -c 2000 # Truncate to 2KB for context safety
Using WebFetch — When You Need AI Processing
WebFetch({
url: 'https://api.example.com/search?q=test',
prompt:
'Extract the top 5 results with their titles and descriptions. Format as a numbered list.',
});
When to use which:
Scenario
Tool
Reason
Need raw JSON for further processing
Bash (curl)
Full control, parseable output
Need summarized/extracted data
WebFetch
AI processes response inline
Need to check HTTP status codes
Bash (curl)
WebFetch abstracts status away
Large response (>50KB)
Bash (curl) + truncate
WebFetch may timeout on large pages
HTML page (not JSON)
WebFetch
Converts HTML to markdown
Error Handling
HTTP Status Code Handling:
Status
Meaning
Action
200-299
Success
Parse response, continue
400
Bad Request
Check parameters, fix and retry
401
Unauthorized
Check API key/token, re-authenticate
403
Forbidden
Check permissions, report to user
404
Not Found
Check URL/resource ID, try alternative endpoint
429
Rate Limited
Wait (check Retry-After header), then retry
500-599
Server Error
Wait and retry up to 3 times
Retry with Exponential Backoff:
# Retry pattern for transient errors (429, 5xx)for attempt in 1 2 3; do
RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$URL" -H "Authorization: Bearer $TOKEN")
HTTP_CODE=$(echo"$RESPONSE" | tail -1)
if [ "$HTTP_CODE" -lt 400 ]; thenbreak# Successfiecho"Attempt $attempt failed ($HTTP_CODE), retrying in $((attempt * 2))s..."sleep $((attempt * 2))
done
Response Processing
Parse JSON response (Bash):
# Extract specific fields from JSON responseecho"$BODY" | node -e "
const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
console.log('Total:', data.totalResults);
data.items?.slice(0, 5).forEach((item, i) => {
console.log(\`\${i+1}. \${item.title} — \${item.description?.substring(0, 80)}\`);
});
"
Truncate large responses:
# Safety: never pass >10KB of API response into context
BODY_TRUNCATED=$(echo"$BODY" | head -c 10000)
if [ ${#BODY} -gt 10000 ]; thenecho"[TRUNCATED: Response was $(echo "$BODY" | wc -c) bytes, showing first 10KB]"fi
Phase 5: Chain — Iterative Multi-Call Workflow
Many tasks require multiple API calls chained together. Use the UTCP-inspired iterative pattern:
Chaining Pattern
Iteration 1: Search -> Get list of results
Iteration 2: Get details for top result
Iteration 3: Perform action on result
(max_iterations guard: stop at 5)
The Iteration Guard (MANDATORY)
MAX_ITERATIONS = 5
Before each API call:
IF iteration_count >= MAX_ITERATIONS:
STOP. Summarize what was gathered so far and respond.
ELSE:
Execute the call, increment counter, re-analyze task.
Why this matters: Without an iteration guard, an agent could loop indefinitely calling APIs. UTCP uses a default of 3; we recommend 5 for more complex multi-step workflows.
Chaining Examples
Example 1: Search and Get Details
User: "Find information about the book '1984' by George Orwell"
Iteration 1:
Call: GET https://openlibrary.org/search.json?q=1984+george+orwell&limit=5
Result: Found 5 matches, top result has key "/works/OL1168083W"
Iteration 2:
Call: GET https://openlibrary.org/works/OL1168083W.json
Result: Full book details (title, description, subjects, covers)
Task complete: Return summarized book information.
Example 2: GitHub — Find and Analyze a Repository
User: "What are the most recent issues in the react repository?"
Iteration 1:
Call: GET https://api.github.com/repos/facebook/react/issues?state=open&per_page=10&sort=created
Headers: Authorization: Bearer $GITHUB_TOKEN
Result: 10 most recent open issues
Task complete: Summarize issue titles, labels, and dates.
Example 3: Multi-API Chain
User: "Find news about AI safety and summarize the top article"
Iteration 1:
Call: GET https://newsapi.org/v2/everything?q=AI+safety&sortBy=publishedAt&pageSize=5
Headers: X-Api-Key: $NEWS_API_KEY
Result: 5 articles with titles, URLs
Iteration 2:
Call: WebFetch({ url: articles[0].url, prompt: "Summarize this article in 3 bullet points" })
Result: Article summary
Task complete: Return article title + summary.
Real-World API Examples
GitHub API (Bearer Token Auth)
# List repositories for a user
curl -s -X GET "https://api.github.com/users/octocat/repos?sort=updated&per_page=5" \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer $GITHUB_TOKEN"
Tool Template:
{"name":"github_list_repos","description":"List repositories for a GitHub user, sorted by most recently updated","base_url":"https://api.github.com/users/{username}/repos","method":"GET","auth":{"type":"bearer","header":"Authorization","env_var":"GITHUB_TOKEN","prefix":"Bearer "},"parameters":{"username":{"type":"string","required":true,"in":"path","description":"GitHub username"},"sort":{"type":"string","required":false,"in":"query","description":"Sort field: created, updated, pushed, full_name","default":"updated"},"per_page":{"type":"integer","required":false,"in":"query","description":"Results per page (max 100)","default":10}}}
Open Library API (No Auth)
# Search for books
curl -s -X GET "https://openlibrary.org/search.json?q=george+orwell&limit=5" \
-H "Accept: application/json"
JSONPlaceholder (Testing/Prototyping)
# GET all posts
curl -s https://jsonplaceholder.typicode.com/posts?_limit=5
# POST new item
curl -s -X POST https://jsonplaceholder.typicode.com/posts \
-H "Content-Type: application/json" \
-d '{"title": "Test Post", "body": "Hello world", "userId": 1}'
Weather API (API Key Auth)
# Get current weather
curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5074&longitude=-0.1278¤t_weather=true"
Context Management for Large Responses
API responses can be very large. Apply these rules to prevent context overflow:
Response Size Limits
Response Size
Action
< 5 KB
Use full response
5-20 KB
Extract relevant fields only
20-50 KB
Summarize via WebFetch or node script
> 50 KB
Truncate to first 5KB + count remaining
Extraction Pattern (Recommended for Large Responses)
# Instead of dumping full response, extract what you need
curl -s "https://api.example.com/search?q=test" | node -e "
const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
// Extract only what the user asked for
const results = data.results.slice(0, 5).map(r => ({
id: r.id,
title: r.title,
summary: r.description?.substring(0, 200)
}));
console.log(JSON.stringify(results, null, 2));
"
Security Checklist
All API keys stored in environment variables (never in code/commands)
HTTPS used for all API calls (never HTTP for authenticated requests)
Response data validated before use (check status codes)