API Integration Agent
Build an agent that can call any REST API based on a YAML tool definition — no Python code required. This tutorial integrates three APIs: Stripe (payments), HubSpot (CRM), and SendGrid (email).
Anatomy of a REST Tool
# tools/stripe.yaml
tools:
stripe_list_customers:
type: rest
description: "List Stripe customers, optionally filtered by email"
url: "https://api.stripe.com/v1/customers"
method: GET
auth:
type: bearer
token: "${STRIPE_SECRET_KEY}"
params:
email: {type: string, required: false}
limit: {type: integer, default: 10, max: 100}
output_path: "$.data" # JSONPath to extract from response
stripe_create_payment_link:
type: rest
description: "Create a Stripe payment link for a product"
url: "https://api.stripe.com/v1/payment_links"
method: POST
auth:
type: bearer
token: "${STRIPE_SECRET_KEY}"
body:
line_items:
- price: "{{ price_id }}"
quantity: "{{ quantity | default(1) }}"CRM Tools (HubSpot)
# tools/hubspot.yaml
tools:
hubspot_create_contact:
type: rest
url: "https://api.hubapi.com/crm/v3/objects/contacts"
method: POST
auth:
type: bearer
token: "${HUBSPOT_API_KEY}"
body:
properties:
email: "{{ email }}"
firstname: "{{ first_name }}"
lastname: "{{ last_name }}"
company: "{{ company | default('') }}"
hubspot_update_deal_stage:
type: rest
url: "https://api.hubapi.com/crm/v3/objects/deals/{{ deal_id }}"
method: PATCH
auth:
type: bearer
token: "${HUBSPOT_API_KEY}"
body:
properties:
dealstage: "{{ stage }}"The Agent
# revenue-ops-agent.yaml
name: revenue-ops
description: "Revenue operations automation across Stripe, HubSpot, SendGrid"
llm:
model: gpt-4o
temperature: 0
system_prompt: |
You are a revenue operations agent. Automate tasks across payment,
CRM, and email systems. Always confirm before creating or deleting data.
For financial operations, log every action with amounts and IDs.
tools:
- stripe_list_customers
- stripe_create_payment_link
- hubspot_create_contact
- hubspot_update_deal_stage
- sendgrid_send_transactional
approval_required:
- stripe_create_payment_link # Must confirm before creating payment links
- sendgrid_send_transactional # Must confirm before sending emailsExample Tasks
# Natural language tasks the agent can handle:
openclaw run --config revenue-ops-agent.yaml \
"Find all Stripe customers who signed up in January 2025 and create HubSpot contacts for each"
openclaw run --config revenue-ops-agent.yaml \
"Create a payment link for our Pro plan ($99/mo) and send it to alice@example.com"
openclaw run --config revenue-ops-agent.yaml \
"Move all HubSpot deals in 'Proposal Sent' stage that are older than 30 days to 'Needs Follow-Up'"OAuth 2.0 Support
# For OAuth-protected APIs (e.g., Google APIs)
tools:
google_calendar_list_events:
type: rest
url: "https://www.googleapis.com/calendar/v3/calendars/primary/events"
method: GET
auth:
type: oauth2
client_id: "${GOOGLE_CLIENT_ID}"
client_secret: "${GOOGLE_CLIENT_SECRET}"
token_url: "https://oauth2.googleapis.com/token"
scopes: ["https://www.googleapis.com/auth/calendar.readonly"]
token_cache: ~/.openclaw/tokens/google.json # Cached refresh tokenWhat This Agent Does
This tutorial builds an agent that integrates with external APIs — reading data from REST endpoints, posting updates, polling for status changes, and composing results from multiple APIs into a unified view. The example connects to a project management API (GitHub Issues) and a notification API (Slack-compatible webhook), but the pattern applies to any REST API combination your workflow needs.
Step 1 — Agent Configuration
Create api-integration-agent.yaml:
agent:
name: api-integration
description: Integrates data from multiple external APIs
system_prompt: |
You are an API integration specialist. You can call external APIs
using the http_request tool. When working with APIs:
- Always check response status codes — treat 4xx as user errors, 5xx as API errors
- Respect rate limits: if you receive a 429, wait the time specified in
Retry-After header before retrying (default 60s if header absent)
- Never log or display raw credentials from API responses
- For paginated endpoints, retrieve all pages before processing unless
explicitly told to limit results
llm:
model: claude-3-5-sonnet-20241022
temperature: 0.1
max_tokens: 4096
tools:
- name: http_request
enabled: true
config:
allowed_domains:
- api.github.com
- hooks.slack.com
timeout: 30
max_response_size: 1048576 # 1MB
- name: file_write
enabled: true
config:
allowed_dirs:
- ./output
prompt_vars:
github_token: "${GITHUB_TOKEN}"
slack_webhook: "${SLACK_WEBHOOK_URL}"
Step 2 — Fetch Data from GitHub
openclaw run --config api-integration-agent.yaml --task "Fetch all open issues from the repository 'owner/repo' using the GitHub API.
Use the Authorization header: 'Bearer {{github_token}}'.
Filter to issues labeled 'bug' created in the last 7 days.
Sort by creation date, newest first.
Save the results to output/recent-bugs.json"
Step 3 — Post a Digest to Slack
openclaw run --config api-integration-agent.yaml --task "Fetch recent bugs from GitHub (same as before) and post a summary
to the Slack webhook at {{slack_webhook}}.
Format the Slack message as:
*Daily Bug Report — [date]*
Total new bugs: N
- [issue title] - [assignee or Unassigned] - [URL]
(list top 5, then 'and N more' if there are more than 5)
Send the POST request with Content-Type: application/json"
Step 4 — Cross-API Data Joining
One of the most powerful use cases for an API integration agent is joining data across systems that don't natively integrate. For example, fetch a list of tickets from your support system, look up the assigned engineer's details from your HR API, and join them to produce a workload report by person. The agent handles the API calls, parsing, and joining logic using natural language instructions rather than requiring custom code for each integration.
Step 5 — Polling and Change Detection
For monitoring workflows, run the agent on a schedule to detect changes. On each run, the agent fetches the current API state, compares it to a saved snapshot from the previous run, identifies what changed, and triggers notifications if changes match alert criteria. Save the state to a file after each successful run. The agent performs the comparison and decision automatically — no custom change detection code required.
Troubleshooting
If the agent cannot access an API, verify the domain is in the allowed_domains list — the agent will refuse to contact domains not explicitly permitted. If you see authentication errors, confirm your environment variables are set: echo $GITHUB_TOKEN. For APIs requiring OAuth flows, generate a personal access token or service account token offline and inject it as an environment variable rather than implementing OAuth in the agent itself.
Handling API Versioning and Breaking Changes
APIs evolve, and version changes can silently break your integration. Defensively specify the API version in every request — use the Accept: application/vnd.api+json;version=2 header or the version-specific URL path rather than relying on the default. When an API deprecates a version, you'll receive a deprecation warning in the response headers before it breaks — add a check to your agent's instructions: "If you see a Deprecation header in any response, include it in your output as a warning that requires attention."
Test your integration with the API's sandbox or staging environment before pointing it at production. Most API providers offer sandbox environments with the same interface but simulated data. Run your full integration workflow in the sandbox first, verify the output is correct, then switch the base URL to production. This practice prevents discovering integration bugs by causing real data mutations in production systems.
Idempotent Operations
When an API call fails partway through a multi-step operation, you need to know whether to retry or continue. Design your agent's API operations to be idempotent where possible — the same operation performed twice should have the same effect as performing it once. For APIs that support idempotency keys (many payment and messaging APIs do), include them in create operations. Instruct the agent: "Before creating a resource, check if a resource with the same identifier already exists — if it does, use the existing one rather than creating a duplicate."
Building a Local API Mock for Testing
For testing your integration agent without making real API calls, create a simple local mock server that returns pre-defined responses for your expected API calls. Configure the agent to point at localhost:8080 during testing by setting a test-specific config file with the mock server URLs in the allowed_domains list. Testing against a mock lets you verify the agent's data processing and decision logic without rate limit concerns, authentication issues, or costs from real API calls. Once the agent behaves correctly against the mock, test against the real API's sandbox for final validation.
Building Reusable API Connector Modules
Once you've built and tested an API integration for a specific service, package the agent configuration and task templates as a reusable connector module. Store the domain-specific configuration — allowed domains, authentication pattern, known endpoint paths — in a dedicated YAML file. Anyone who needs to build a workflow involving that API starts from your connector rather than from scratch. Over time, your team builds a library of reliable, tested API connectors that dramatically accelerates new integration development. Document each connector's capabilities, limitations, and any known rate limiting constraints so users can choose the right approach for their use case.
Webhook-Triggered Integration
Rather than polling APIs on a schedule, configure webhooks to trigger your integration agent reactively. When a new GitHub issue is created, a webhook fires — your integration agent receives the payload, enriches it with data from other APIs (for example, adding team member context from your HR system or adding priority score from your product roadmap), and posts the enriched notification to the relevant Slack channel. Reactive webhook-driven integrations are more efficient than polling (no unnecessary API calls when nothing has changed) and are more timely (the action happens within seconds of the triggering event rather than waiting for the next scheduled poll).