Engineering · · 4 min read
A background job needs a result contract the agent can finish
Define submission, polling, terminal failure, result retrieval, and cleanup so an asynchronous task produces usable work.
The agent submits a report export and receives a job identifier. It tells the user the report is ready. The download is still being generated, and a later worker error prevents it from ever appearing. The submission response was valid, and the completion claim was premature.
A public MCP discussion about multi-step execution records asks how to represent a workflow beyond individual calls. A background job needs a smaller contract: how the agent moves from accepted work to a usable result.
Define the states in business terms#
- Submission: the provider accepted a request.
- Processing: work is still underway.
- Terminal success: the provider completed its job.
- Artifact availability: the intended consumer can retrieve the output.
The last two events can occur at different times. Microsoft's asynchronous request-reply pattern separates acceptance from status polling; use the provider contract to decide which response proves each stage.
An export tool returns the operation identifier, a permitted status path, and enough information to resume tracking. The model must not invent a polling URL from the identifier. Include the expiry or documented retrieval window when the provider supplies one.
Follow a report through completion#
An agent generating a monthly support report gets job J-72 from submission, stores it, and keeps preparing the sections that do not depend on the export.
The status routine later sees success, retrieves the artifact, and checks that the file is nonempty, matches the requested account and period, and is reachable through the delivery path before the agent presents it as ready.
If the job succeeds but the download fails, recovery retries retrieval or obtains a fresh permitted link. Another export starts only if the artifact cannot be recovered and the provider contract permits resubmission.
If the job fails, preserve its terminal error and any partial artifact, decide whether partial output helps, and never label it complete because a file exists.
| Stage | Durable information | Next step |
|---|---|---|
| Accepted | Job ID, target, requested period | Track the original job |
| Processing | Last status and next check time | Capped polling |
| Failed | Terminal error and partial result reference | Explain or repair the cause |
| Succeeded | Result identifier | Retrieve and validate output |
| Delivered | Usable artifact reference | Complete the user task |
Keep polling outside the model loop#
Use a deterministic status routine with a deadline, provider-aware intervals, and a maximum number of checks; a model call asking whether the job finished adds nothing.
The task can continue independent work while waiting but must not launch an identical job because a poll returned an unchanged status. Keep the operation identity through retries, restarts, and follow-ups.
When the deadline expires, return the job identifier, last observed state, and next recovery action, with later notification if the application supports it or a way to resume checking the same job.
Handle cancellation and expiry separately#
Stopping the parent task can stop polling without canceling the provider job. If the provider supports cancellation, invoke it within the user's authority and confirm the resulting state, since a cancellation request does not prove no artifact will be created.
An expired download link does not mean the report failed; the agent needs a refreshed link. A deleted artifact and an expired signed URL need different recovery.
The guide to stopping a running agent covers the broader control question; here, keep the external operation state visible after the conversation stops waiting.
Verify the final consumer's path#
A connector service can read an artifact the user cannot open. Test delivery through the intended access path and never expose a private provider URL or service-local path the recipient cannot use.
Test accepted-then-failed, success with a missing artifact, expired-link recovery, and a process restart between submission and polling. A synchronous demo skips all four.
Keep the job identifier on the user's task until the artifact is delivered or the failure is resolved. The action lifecycle and SDK recovery guide connect submission, status, and result for routed calls. Save the job contract with the integration so the next export produces a finished report.