agent.run(files=[File(...)]) handles one document. Folders, queues, and nightly drops also need concurrency limits, retry policy, and idempotent writes. The patterns below cover bounded async batches, in-process background runs, durable AgentOS queues, and scheduled endpoints.
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.
concurrency based on the model quota and downstream write capacity.
Background runs for long jobs
background=True returns a pending run while an asyncio task continues in the current process. Poll the persisted run state when the caller should not wait for the model response.
agent.arun() task does not resume from the run record. Submit through an AgentOS durable queue when execution must survive process failure.
Durable background runs
durable_intake.py
202, and a live replica can claim queued work after a restart. The default max_attempts=1 reports an interrupted claimed job as failed without silently repeating possible side effects. Set max_attempts=2 or higher for automatic crash retries after making the target idempotent.
Poll /agents/invoice-extractor/runs/{run_id}?session_id={session_id} for the result. See Durable Queue for submission, polling, retry, and dead-letter operations.
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.scheduled_intake.py
scheduled_intake.py module, create the schedule before starting the server. ScheduleManager writes to the same db the AgentOS polls.
if_exists="update" updates a schedule found by name instead of creating another schedule. Agno v3.0.4 enforces schedule-name uniqueness per owner. The lookup and write are separate operations, so simultaneous first-time creation can still race and one insert can fail with a uniqueness error. Run schedule bootstrap once or retry that conflict when multiple application workers can start concurrently. The option also does not make the scheduled endpoint idempotent. The executor retries failed HTTP or run attempts with the configured delay, and each attempt writes a row to agno_schedule_runs.
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 execution attempt creates a row inagno_schedule_runs with status and timing. run_id and session_id are present when the target run starts successfully. Inspect recent activity with:
schedule_id and an incrementing attempt. Monitor these rows and route exhausted failures to your operational queue.