Botpress Execute Code card: call Sume's API without waiting on the run
Botpress's Execute Code card offers Axios for HTTP and no external libraries. Start a Sume run in one card and collect the result by webhook, not a wait loop.

Start the Sume run in one Execute Code card and do not wait for it. Botpress documents Axios as the way to make API requests there and says you cannot import external libraries, so the card is a good place for a single POST and a poor place for a polling loop. Sume returns 202 right away, which fits.
What the Botpress page says
The Execute Code card runs JavaScript inside a node. The docs say you cannot import external libraries, point to Axios for API requests, and recommend handling slow or failed requests with try and catch, timeouts or fallback flows. It does not state an execution time limit, so design as if the card should finish quickly.
Split the work in two
| Stage | What happens | Sume side |
|---|---|---|
| Start | Axios POST with the instruction, a cap and a callback URL | 202 and an agent.run receipt with id and status_url |
| Store | Write the run id to a Botpress variable or table | Receipt id equals the later webhook request_id |
| Receive | A webhook route in your own backend or integration | One signed POST on agent.run.terminal |
| Reply | Send the text or media URL back to the user | output.text, output.images, output.videos |
The request
Send this body from the card with Axios, with the key read from a secret rather than typed into the card. Use one credential header, either Authorization: Bearer or x-api-key.
Keep the instruction short and put variable data in the input object when the agent needs structured context. Sume writes it to a file the agent reads as data, rather than mixing it into the prompt, which keeps user text from rewriting your instruction.
{
"instruction": "Write a friendly two-line reply about the order status",
"generation_spend_cap_usd": 0.5,
"communication": { "webhook_url": "https://example.com/hooks/sume" }
}Handling failure
Wrap the call in try and catch and route a failure to a fallback message. Distinguish errors: a 400 invalid_request usually means the cap is missing, a 403 insufficient_scope means the key lacks agent_completions:write, and a 429 names the bucket in error.details.scope, with retry-after telling you when to try again. Writes have their own per-minute bucket by plan, so a busy bot on a free plan can hit it before a larger one would.
If the webhook never arrives, a manual GET /v1/agent-runs/{id} from a later turn returns the same receipt. A delivery failure does not change the run. Keep the cap small for chat use, because an unattended agent turn can generate media, and the cap is what stops a loop from spending more than you intended.
Finally, give each run an Idempotency-Key built from the conversation and message ids. If Botpress retries the card after a timeout, Sume returns the original receipt with idempotency_hit: true instead of starting a second, paid run.
Sources
More in Integrations
- Braze Connected Content has 2 seconds: pre-render the Sume clip
Braze drops Connected Content that answers in over 2 s. A Sume avatar job takes longer, so render first, store the URL, and let the campaign read a fast lookup.
- Braze 404 renders empty: a fallback while the Sume clip renders
Braze turns a 404 into an empty string. Sume returns 409 job_not_completed until a result exists. Map one to a fallback URL so no message goes out blank.
- Braze retries a 500: keep the Sume job submit idempotent
Braze sends 500 and 502 responses to retry logic, and a :retry option exists. Give every Sume submit a stable Idempotency-Key so a retry is not a second bill.
- Cloudflare Worker: keep the image model id in KV and swap it live
A Worker that proxies POST /v1/images and reads the Sume model id from Workers KV, so replacing gpt-image-1 is a wrangler command, not a deploy.
Written by Sume