Skip to main content

Custom External Agents: Full Code Control

A Runnable Agent uses the Agent SDK (@openserv-labs/sdk) with runnable capabilities — each has a run() function where you write custom TypeScript. Need to call an API? Fetch data? Use this.generate() to delegate LLM calls to the platform using your OpenServ credits (no API key required).

The Concept

  1. Define: Create an Agent with a systemPrompt and add capabilities with inputSchema (Zod) and a run() function.
  2. Provision: Call provision() to register the agent, create a workflow, and set up a trigger — all in one call.
  3. Run: Call run(agent) to start. Tunneling is automatic, no ngrok needed.
⚠️ run(agent) starts a local server. Make sure it’s running before triggering any webhooks. Deploy to a VPS for always-on production use. Both packages are needed:
Best for:
  • API integrations (GitHub, Slack, Twitter, databases)
  • Web scraping & data transformation
  • Complex multi-step logic with LLM reasoning via this.generate()
  • Agents that need external secrets or API keys

The Master Template

Copy & Paste:

Example Recipes

1. The “GitHub Profile Analyzer”

Copy & Paste:

2. The “DeFi Market Briefing” (No API Key Needed)

Uses Hyperliquid’s open API — completely free, no authentication required. Shows how to fetch live on-chain data and turn it into an AI-written report. Copy & Paste:

3. The “Runnable Agent + Marketplace Agent” Pipeline

Your custom agent does step 1 (custom code), then a marketplace agent handles step 2 (AI reasoning). Copy & Paste:

Key Concepts

this.generate() — Platform-Delegated LLM Calls

Inside any run() function, call this.generate() to use OpenServ’s LLM. No API key needed — uses your credits. The action parameter is required.

Runless vs Runnable Capabilities

TypeWhen to UseHas run()?
RunlessSimple text processing. Platform handles the LLM call.No
RunnableCustom code, external APIs, data fetching, side effects.Yes
Both are defined with agent.addCapability() — the difference is whether you include a run() function.

Deployment

Local: Just run(agent). Tunnel is automatic. No ngrok. Production: Set DISABLE_TUNNEL=true and provide endpointUrl in provision().

Debugging

If something isn’t working, paste this to OpenClaw: