Skip to content

Collect Foundry results returned as HTTP 202 - #395

Draft
ggprior wants to merge 2 commits into
mainfrom
georg/foundry-202-collect
Draft

ggprior wants to merge 2 commits into
mainfrom
georg/foundry-202-collect

Conversation

@ggprior

@ggprior ggprior commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

A Foundry endpoint answers HTTP 202 when a fit outlives the platform's request window: the body names the fit instead of carrying a prediction. predict* read result["prediction"] from it unconditionally and raised KeyError, so a Thinking fit long enough to be handed off could never be retrieved — which is every Thinking fit on a non-trivial dataset.

_invoke now treats 202 as "not ready yet": it takes the model_id from the body and re-sends until the result arrives.

  • Paced by the response's Retry-After, falling back to 10s. Only the delta-seconds form is honoured; an HTTP-date falls back rather than failing a collect that is otherwise progressing.
  • Bounded by a new collect_timeout_s (default 2h). On expiry it raises TimeoutError and says the fit continues server-side, so calling again collects it.
  • A 202 with no model_id raises FoundryEndpointError rather than looping forever.

Follow-up requests carry only the id and the test rows. _build_request_body already omits training data when a cached id is set, so the payload drops from the full dataset to X_test on every attempt after the first — the difference between re-uploading hundreds of megabytes per poll and a few.

No change to the success path, and nothing new on the wire: the id was already returned on a 200 and already accepted as context.model_id.

Testing

tests/unit/test_foundry_collect.py drives the loop with respx: a 202 then a 200, several 202s in a row, a 202 lacking a model_id, and an exhausted collect budget. It asserts the resend drops x_train/y_train and carries context.model_id, and covers Retry-After parsing including the HTTP-date fallback and a negative delta.

The existing unit suite (333 tests) passes unchanged.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MuU9cPnmjTezLecPsK9HPd

ggprior and others added 2 commits September 21, 2026 08:55
A fit that outlives the platform's request window answers HTTP 202 naming the
fit rather than the prediction. `predict*` passed that body straight to
`result["prediction"]` and raised KeyError, so a long Thinking fit could not
be retrieved at all.

It now collects: the id in the 202 is re-sent until the result is ready,
paced by `Retry-After` and bounded by the new `collect_timeout_s`. Those
follow-ups carry only the id and the test rows, so the training data is not
shipped again — at a large context that is the whole payload on every attempt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MuU9cPnmjTezLecPsK9HPd
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MuU9cPnmjTezLecPsK9HPd

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant