Claude-code-plugins-plus lindy-sdk-patterns
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/lindy-pack/skills/lindy-sdk-patterns" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-lindy-sdk-patterns && rm -rf "$T"
plugins/saas-packs/lindy-pack/skills/lindy-sdk-patterns/SKILL.mdLindy SDK & Integration Patterns
Overview
Lindy is primarily a no-code platform. External integration happens through three channels: Webhook triggers (inbound), HTTP Request actions (outbound), and Run Code actions (inline Python/JS execution via E2B sandbox). This skill covers patterns for each.
Prerequisites
- Lindy account with active agents
- Node.js 18+ or Python 3.10+ for webhook receivers
- Completed
setuplindy-install-auth
Pattern 1: Webhook Trigger Integration
Your application fires webhooks to wake Lindy agents:
// lindy-client.ts — Reusable Lindy webhook trigger client class LindyClient { private webhookUrl: string; private secret: string; constructor(webhookUrl: string, secret: string) { this.webhookUrl = webhookUrl; this.secret = secret; } async trigger(payload: Record<string, unknown>): Promise<{ status: number }> { const response = await fetch(this.webhookUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${this.secret}`, 'Content-Type': 'application/json', }, body: JSON.stringify(payload), }); if (!response.ok) { throw new Error(`Lindy webhook failed: ${response.status} ${response.statusText}`); } return { status: response.status }; } async triggerWithCallback( payload: Record<string, unknown>, callbackUrl: string ): Promise<{ status: number }> { return this.trigger({ ...payload, callbackUrl }); } } // Usage const lindy = new LindyClient( 'https://public.lindy.ai/api/v1/webhooks/YOUR_ID', process.env.LINDY_WEBHOOK_SECRET! ); await lindy.trigger({ event: 'lead.created', name: 'Jane Doe', email: 'jane@co.com' });
Pattern 2: HTTP Request Action (Agent Calling Your API)
Configure a Lindy agent to call your API as an action step:
In Lindy Dashboard — Add HTTP Request action:
- Method: POST
- URL:
https://api.yourapp.com/process - Headers:
,Authorization: Bearer {{your_api_key}}Content-Type: application/json - Body (AI Prompt mode):
Send the processed data as JSON with fields matching the API schema. Include: name from {{trigger.data.name}}, analysis from previous step.
Your API endpoint receives the call:
// Your API receiving Lindy agent calls app.post('/process', async (req, res) => { const { name, analysis } = req.body; const result = await processData(name, analysis); res.json({ result, processedAt: new Date().toISOString() }); });
Pattern 3: Run Code Action (E2B Sandbox)
Execute Python or JavaScript directly in Lindy workflows. Code runs in isolated Firecracker microVMs with ~150ms startup time.
Python example (data transformation in a workflow):
# Run Code action — Python # Input variables: raw_data (string from previous step) import json data = json.loads(raw_data) # Input vars are always strings # Process cleaned = [ {"name": item["name"].strip(), "score": float(item["score"])} for item in data["items"] if float(item["score"]) > 0.5 ] # Sort by score descending cleaned.sort(key=lambda x: x["score"], reverse=True) # Return value accessible as {{run_code.result}} in next step return json.dumps({"filtered_count": len(cleaned), "items": cleaned})
JavaScript example (API call + processing):
// Run Code action — JavaScript // Input variables: query (string), api_key (string) const response = await fetch(`https://api.example.com/search?q=${query}`, { headers: { 'Authorization': `Bearer ${api_key}` } }); const data = await response.json(); const summary = data.results.map(r => `${r.title}: ${r.snippet}`).join('\n'); return JSON.stringify({ count: data.results.length, summary });
Run Code outputs (available to subsequent steps):
| Output | Contents |
|---|---|
| Value from statement |
| stdout from / |
| Error output for debugging |
Available Python libraries: pandas, numpy, scipy, scikit-learn, matplotlib, requests, aiohttp, beautifulsoup4, nltk, spacy, openpyxl, python-docx
Key constraint: All input variables arrive as strings. Cast explicitly:
count = int(count_str), data = json.loads(json_str)
Pattern 4: Callback Pattern (Async Two-Way)
Send a
callbackUrl in your webhook payload. Lindy can respond back using
the Send POST Request to Callback action:
// Your app triggers Lindy with a callback URL await lindy.trigger({ event: 'analyze.request', data: { text: 'Analyze this quarterly report...' }, callbackUrl: 'https://api.yourapp.com/lindy-callback' }); // Your callback handler receives Lindy's response app.post('/lindy-callback', (req, res) => { const { analysis, sentiment, summary } = req.body; saveAnalysis(analysis); res.sendStatus(200); });
Pattern 5: Retry with Exponential Backoff
async function triggerWithRetry( client: LindyClient, payload: Record<string, unknown>, maxRetries = 3 ): Promise<void> { for (let attempt = 0; attempt <= maxRetries; attempt++) { try { await client.trigger(payload); return; } catch (error: any) { if (attempt === maxRetries) throw error; const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s console.warn(`Retry ${attempt + 1}/${maxRetries} in ${delay}ms`); await new Promise(r => setTimeout(r, delay)); } } }
Error Handling
| Pattern | Failure Mode | Solution |
|---|---|---|
| Webhook trigger | 401 Unauthorized | Verify Bearer token matches dashboard secret |
| HTTP Request action | Target API unreachable | Check URL, verify HTTPS, test with curl |
| Run Code | Timeout | Avoid infinite loops; keep execution under 30s |
| Run Code | Import error | Use only pre-installed libraries (see list above) |
| Callback | Callback URL unreachable | Ensure HTTPS endpoint is publicly accessible |
Resources
Next Steps
Proceed to
lindy-core-workflow-a for full agent creation workflows.