Deploy a worker
Run the agent as a worker that registers, reports load, and drains.
A worker runs agent sessions as jobs: it registers with a dispatch source, reports load, accepts or rejects offered jobs, and runs each one to completion. This is how the same agent code goes from a single process to a fleet. For the model behind it see Architecture.
Create a worker
The only required option is the Entrypoint — it runs once per assigned job and
builds the session for that job.
w, err := worker.New(worker.WorkerOptions{
Entrypoint: func(ctx context.Context, jc *worker.JobContext) error {
session, err := agents.NewSession(agents.Config{
LLM: "openai/gpt-4o", STT: "openai/gpt-4o-mini-transcribe", TTS: "openai/tts-1",
// bind the job's transport I/O here
})
if err != nil {
return err
}
jc.OnShutdown(func() { _ = session.Close(context.Background()) })
agent := agents.MustNewAgent(agents.AgentOptions{Instructions: "be helpful"})
return session.Start(ctx, agents.StartOptions{Agent: agent})
},
})
if err != nil {
return err
}JobContext carries the Job, WorkerID, and connection URL/Token.
Register cleanup with jc.OnShutdown — callbacks run in reverse order when the
job ends.
Run it against a dispatch source
Run registers the worker and processes jobs until the context is cancelled. It
must be called once.
if err := w.Run(ctx, source); err != nil {
return err
}The source is a DispatchSource — for the single-binary MVP that's an embedded
dispatcher; behind a LiveKit server it's the server connection. In the LiveKit
case the server mints each job's room URL and Token and hands them to the
entrypoint on the JobContext — see
Connecting to a room.
Tuning capacity
| Option | Default | Notes |
|---|---|---|
MaxJobs | GOMAXPROCS | Concurrent jobs; feeds the default load function. |
LoadThreshold | DefaultLoadThreshold | Effective load at which the worker reports full. |
Load | concurrency-based | Custom load function. |
OnRequest | accept-all | Accept/reject offered jobs. |
WorkerType | WorkerTypeRoom | Room (one job per room) or Publisher (one per publisher). |
StatusInterval / PingInterval | defaults | Reporting / heartbeat cadence. |
See Scaling & load for how these interact with placement.
Draining for deploys
func (w *Worker) Drain(ctx context.Context) errorDrain stops accepting new jobs and waits for running ones (and
accepted-but-unassigned reservations) to finish — so a rolling deploy or scale-in
never drops a live call. See Graceful drain.
Related
- Reference: Worker & dispatch
- Architecture · Scaling & load