Introduction
The real power of the Paperclip API emerges when you combine multiple endpoints into automated workflows. This lesson shows how to build practical automations: auto-assigning issues, monitoring budgets, using CLI JSON output for scripts, and setting up webhook notifications.
Key Concepts
- Multi-Call Workflows: Combining multiple API calls in sequence to automate complex processes.
- Auto-Assignment: Matching issues to agents based on capabilities and current workload.
- Budget Monitoring: Polling cost summaries and triggering alerts when thresholds are approached.
- CLI JSON Output: The
--jsonflag on CLI commands outputs structured data for scripting. - Webhook Integration: Using the HTTP adapter to send notifications to external services.
Real World Context
You run a nightly automation that scans the backlog for unassigned issues, matches them to available agents, assigns them, and sends a Slack notification. If any agent is above 70% budget utilization, the automation flags them for review.
Deep Dive
Auto-Assign Issues
A workflow that matches unassigned backlog issues to agents:
typescriptasync function autoAssignIssues(companyId: string, token: string) { const headers = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }; // 1. Get unassigned backlog issues const issuesRes = await fetch( `http://localhost:3100/api/companies/${companyId}/issues?status=backlog`, { headers } ); const issues = await issuesRes.json(); const unassigned = issues.filter((i: any) => !i.assigneeId); // 2. Get active agents const agentsRes = await fetch( `http://localhost:3100/api/companies/${companyId}/agents`, { headers } ); const agents = await agentsRes.json(); const active = agents.filter((a: any) => a.status === 'active'); // 3. Round-robin assignment for (let i = 0; i < unassigned.length; i++) { const agent = active[i % active.length]; await fetch(`http://localhost:3100/api/issues/${unassigned[i].id}`, { method: 'PATCH', headers, body: JSON.stringify({ assigneeId: agent.id }), }); } return { assigned: unassigned.length }; }
This function fetches unassigned issues and active agents, then assigns in a round-robin fashion.
Budget Monitoring
typescriptasync function checkBudgets(companyId: string, token: string) { const res = await fetch( `http://localhost:3100/api/companies/${companyId}/costs/summary`, { headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } } ); const summary = await res.json(); if (summary.utilizationPercent >= 80) { console.warn(`Budget at ${summary.utilizationPercent}% utilization`); } return summary; }
CLI JSON Output
bashpaperclip companies list --json | jq '.[] | .name' paperclip agents list --company c1 --json | jq '.[] | select(.status == "active") | .name'
The --json flag outputs structured data that can be piped to jq.
Webhook Notifications
typescriptasync function notifySlack(message: string, webhookUrl: string) { await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: message }), }); }
Common Pitfalls
- Not handling API errors in automation loops: If one call fails, log the error and continue.
- Polling too frequently: Check cost summaries once per hour, not per minute.
- Hardcoding agent IDs: Use the agents list endpoint to discover agents dynamically.
Best Practices
- Build idempotent automations that produce the same result when run multiple times.
- Add logging to every automation step for traceability.
- Start with simple round-robin and add capability matching as you scale.
Summary
- Combine multiple API calls to build automated workflows
- Auto-assign issues by matching backlog items to active agents
- Monitor budget utilization and trigger alerts at threshold percentages
- Use --json CLI output for shell-based scripting with jq
- Integrate external notifications via webhooks
- Build idempotent, error-tolerant automations with proper logging
Code Examples
typescript
async function checkBudgets(companyId: string, token: string) {
const res = await fetch(
`http://localhost:3100/api/companies/${companyId}/costs/summary`,
{ headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }
);
const summary = await res.json();
if (summary.utilizationPercent >= 80) {
console.warn(`Budget at ${summary.utilizationPercent}%`);
}
return summary;
}