AI agent calls are async — you start a job and wait for it to complete. There are two ways to handle the wait: poll the job endpoint until it's done, or have the platform call your webhook when it's done.
Polling is the default on Runcept. You call GET /api/v1/jobs/:id on a loop until the status changes.
async function pollJob(jobId) {
while (true) {
await new Promise(r => setTimeout(r, 3000))
const job = await fetch(https://www.runcept.com/api/v1/jobs/${jobId}, {
headers: { Authorization: Bearer ${process.env.RUNCEPT_API_KEY} },
}).then(r => r.json())
if (job.status === 'complete') return job.output
if (job.status === 'failed') throw new Error(job.error)
}
}
Pros: Simple, works anywhere, no infrastructure needed
Cons: Keeps your process alive, makes repeated HTTP calls
With webhooks, you provide a callback URL when starting the job. When the job completes, Runcept POSTs the result to your URL.
// Start the job with a webhook URL
const { job_id } = await fetch('https://www.runcept.com/api/v1/run', {
method: 'POST',
headers: {
Authorization: Bearer ${process.env.RUNCEPT_API_KEY},
'Content-Type': 'application/json',
},
body: JSON.stringify({
agent: 'pr-description',
input: { diff: myDiff },
webhook_url: 'https://your-app.com/api/webhooks/runcept',
}),
}).then(r => r.json())
// Your webhook handler receives the completed job
// POST https://your-app.com/api/webhooks/runcept
// { job_id, status: "complete", output: { ... } }
// Webhook handler (Next.js)
export async function POST(req: Request) {
const { job_id, status, output } = await req.json()
if (status === 'complete') {
await saveResult(job_id, output)
}
return new Response('ok')
}
Pros: Efficient, fire-and-forget, scales well
Cons: Requires a public HTTPS endpoint, need to handle retries
|----------|---------------|