Skip to main content
A single agent.run(files=[File(...)]) handles one document. Production runs see folders, queues, and nightly drops. Three primitives cover the production shape: concurrent runs for ad-hoc batches, background runs for long jobs, scheduled runs for nightly intake.

Concurrent batch over a list

The simplest batch is a folder of files. agent.arun is async, so a semaphore plus asyncio.gather is enough.
A semaphore is the smallest concurrency control. It keeps you under the provider’s rate limit and bounds memory. Tune the concurrency to the slowest of: your rate quota, your DB write throughput, your memory budget.

Background runs for long jobs

Sync runs hold an HTTP connection until the model returns. For multi-page contracts or scanned PDFs that take minutes, start the run in the background and poll.
The background run is persisted in db. The agent process can restart and a different process can poll the same run_id. That is the durability property: state lives in the database, not in the calling process.

Scheduled batch with retries

For nightly intake (an SFTP drop, a Drive folder, a queue), put an AgentOS in front of your agent and let the scheduler fire the run on cron.
Then create the schedule in Python. ScheduleManager writes to the same db the AgentOS polls.
if_exists="update" makes the call idempotent. Re-running the bootstrap script does not create duplicates. The scheduler retries on HTTP failure with the configured delay, and every fire writes a row to agno_schedule_runs with status and timing.

Pattern comparison

The scheduler fires endpoints. Endpoints are agents, teams, or workflows. So a nightly job that ingests a folder, extracts each file, and writes to your warehouse is a workflow exposed at /workflows/<id>/runs, scheduled with the same ScheduleManager.create call. See Workflows.

Observability

Every scheduled fire creates a row in agno_schedule_runs with the schedule id, attempt number, status, and the run_id of the underlying agent run. To see the last day of activity:
Failed attempts keep their error text. Retries are separate rows with the same schedule_id and an incrementing attempt. That is the audit trail you can hand to ops.

Production checklist

Next steps

Developer Resources