Error Handling
You Can't Break The Agent
Any unhandled exception in your tool is automatically caught by the agent. It will never crash the process. The error is captured, sent to NINA as a failure event, and the agent continues processing the next message. You don't need try/catch around everything — just write your tool logic and let it fail naturally if something goes wrong.
Exit Codes
| Code | Status | Meaning |
|---|---|---|
0 | Success | Tool completed, output uploaded to S3 |
1 | Failure | Tool failed, error reported to NINA |
-1 | Timeout | Tool exceeded timeout, error reported to NINA |
Handling Errors in Your Tools
Fail Fast (Workflow Stops)
Raise an exception when the error is critical:
@beam_tool(name="strict_scanner")
async def strict_scanner(input_paths, output_path, parameters):
if not parameters.get('target'):
raise ValueError("Parameter 'target' is required")
return await scan(parameters['target'])
Graceful Degradation (Workflow Continues)
Return error info as output when the workflow should continue:
@beam_tool(name="best_effort_scanner")
async def best_effort_scanner(input_paths, output_path, parameters):
try:
result = await scan(parameters['target'])
return {"status": "success", "data": result}
except Exception as e:
return {"status": "error", "message": str(e)}
What Happens on Failure
- Agent sends a
execution.phase.failedcompletion event to NINA - Message is deleted from the queue (no automatic requeue)
- NINA marks the node as failed
Exception: If the agent process crashes (killed, machine reboots), the message reappears in the queue after the visibility timeout and will be retried. Make sure your tools are safe to re-execute.
Next Steps
- Troubleshooting - Solve common issues
- Creating Tools - Build custom tools