Skip to content

feat(messages): add the Anthropic Message Batches API - #546

Merged
SantiagoDePolonia merged 2 commits into
mainfrom
feat/anthropic-message-batches
Jul 17, 2026
Merged

SantiagoDePolonia merged 2 commits into
mainfrom
feat/anthropic-message-batches

Conversation

@SantiagoDePolonia

@SantiagoDePolonia SantiagoDePolonia commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Implements the Anthropic Message Batches API (/v1/messages/batches) so client.messages.batches.* in the Anthropic SDKs works against GoModel — closing the last gap from the drop-in compatibility work in #543. The dialect is an edge translation over the existing native-batch pipeline (same pattern as /v1/messages, ADR-0007): decode at the edge, reuse the orchestrator/store/budget/usage/audit machinery, render back in the Anthropic shape.

User-visible impact

  • Full endpoint set: create, retrieve, list (limit/after_id), cancel, results (JSONL), and DELETE for ended batches.
  • Any provider, not just Anthropic: each item's params is a Messages request translated to the canonical chat shape, so a Message Batch routes to any provider with native batch support. Verified live: an openai/gpt-4o-mini batch created through the Anthropic SDK, polled to ended, results streamed back as Anthropic-shaped messages, deleted.
  • One resource, two dialects: /v1/messages/batches and /v1/batches are views of the same gateway batch; IDs interconvert (msgbatch_<uuid> ↔ batch_<uuid>).
  • results_url is set once a batch ends and the SDK's results() follows it; successful items are converted to the Anthropic Messages shape regardless of serving provider; provider-native canceled/expired item outcomes map to their dedicated result types.
  • Delete: new Store.Delete across all four persistence backends, an ended-only guard in the orchestrator, and native upstream deletion via a new optional NativeBatchDeleteProvider (implemented for anthropic). Providers without a native delete (OpenAI has none) fall back to gateway-local removal.

Provider-specific behavior

  • OpenAI-compatible providers now accept inline batch requests: the gateway materializes them into an uploaded JSONL input file before POST /batches (the OpenAI batch API is file-only). This fixes inline submissions on the OpenAI dialect's requests[] extension too — previously they were forwarded verbatim and rejected upstream with Missing required parameter: 'input_file_id'.
  • request_counts maps the canonical total/completed/failed aggregates: unfinished requests report as processing while running; after the batch ends, the remainder is attributed by outcome (canceled/expired/errored).

Testing

  • Table-driven unit tests: dialect translators (create decode/validation incl. per-item error indexing, status/counts/timestamps mapping, ID mapping, results JSONL for typed + map-shaped + errored/canceled/expired items), route derivation for the messages paths, endpoint classification, store Delete (memory + sqlite), handler lifecycle (create/get/list/results/cancel/delete incl. the ended-only guard and Anthropic error envelopes), and the inline→file upload in the OpenAI provider.
  • go test ./internal/... green; gofmt/vet clean.
  • Live SDK verification against real providers (Anthropic + OpenAI): full lifecycle as described above; anthropic-native create/retrieve/list/cancel verified (its upstream batch was still processing within the test window — results/delete exercised on the OpenAI path and covered by unit tests for the anthropic result shape).

Docs

docs/advanced/anthropic-messages-api.mdx: endpoints table extended, new Message Batches section with cross-provider notes and an SDK example.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Anthropic Message Batches endpoints: create, list, retrieve, cancel, delete, and stream JSONL results.
    • Enabled interoperability between Anthropic message batches and the gateway’s native OpenAI-compatible batching pipeline.
    • Added inline batch item support for compatible providers by converting requests to file-backed batch inputs.
  • Bug Fixes
    • Improved validation and error reporting for malformed payloads and batch item identifiers.
    • Ensured consistent routing for message-batch paths and delete actions.
  • Documentation
    • Expanded Message Batch documentation, including status handling, provider constraints, and batch input/output details.

Implements /v1/messages/batches as an Anthropic-dialect ingress over the
existing native-batch pipeline (same edge-translation pattern as
/v1/messages, ADR-0007):

- POST/GET/list/cancel/results routes plus DELETE for ended batches.
  Batch IDs are dialect views of one resource: msgbatch_<uuid> here,
  batch_<uuid> on /v1/batches.
- anthropicapi translators: create body ({requests:[{custom_id,params}]})
  decodes each params as a Messages request and translates to canonical
  chat items, so a batch routes to any provider with native batch
  support; egress renders message_batch objects (processing_status,
  request_counts, expires_at, results_url) and the results JSONL with
  successful items converted back to the Anthropic Messages shape.
- /v1/messages/batches* classified as an anthropic-dialect batches
  operation, so error envelopes, audit, usage, budgets, and rate limits
  apply exactly like /v1/batches.
- Delete support through the stack: batchstore.Store.Delete (memory,
  sqlite, postgres, mongo), orchestrator Delete (refresh, ended-only
  guard, store removal), optional NativeBatchDeleteProvider with an
  anthropic implementation; providers without native delete fall back to
  gateway-local removal.
- OpenAI-compatible providers now materialize inline batch requests into
  an uploaded JSONL input file, fixing inline submissions for the
  file-based batch API on both dialects.

Verified live with the Anthropic Python SDK: full lifecycle including an
OpenAI gpt-4o-mini batch created, polled to ended, results streamed as
Anthropic messages, and deleted; plus anthropic-native create, retrieve,
list, and cancel.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab1fc192-dcbb-4e7c-a479-2e8af7ce9c81

📥 Commits

Reviewing files that changed from the base of the PR and between 41a1749 and 83f3878.

📒 Files selected for processing (5)
  • internal/anthropicapi/batch.go
  • internal/anthropicapi/batch_test.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/compatible_provider_test.go
  • internal/server/messages_handler.go
 _____________________________________________
< I'm not sure if this is a bug or a feature. >
 ---------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
📝 Walkthrough

Walkthrough

Adds full Anthropic Message Batches support, translating requests and results through the canonical batch pipeline, exposing lifecycle endpoints, supporting deletion across stores and providers, handling OpenAI-compatible inline inputs, and documenting the API.

Changes

Anthropic Message Batches

Layer / File(s) Summary
Anthropic batch translation
internal/anthropicapi/batch.go, internal/anthropicapi/batch_test.go
Adds request validation, canonical batch translation, ID aliases, status/count mapping, response rendering, and JSONL result encoding with focused tests.
Canonical routing and deletion
internal/core/*, internal/batch/*, internal/gateway/batch_orchestrator.go
Normalizes message-batch routes, adds delete actions and storage methods, and orchestrates terminal deletion with provider and persistence handling.
Provider batch support
internal/providers/anthropic/batch.go, internal/providers/openai/compatible_provider.go, internal/providers/router.go
Adds native Anthropic deletion, unsupported-provider fallback signaling, and inline OpenAI-compatible batch input uploads.
Message batch HTTP API
internal/server/http.go, internal/server/messages_handler.go, internal/server/messages_batch_service.go, internal/server/*test.go
Registers and implements create, list, retrieve, cancel, delete, and results endpoints with lifecycle and validation coverage.
Message batch documentation
docs/advanced/anthropic-messages-api.mdx
Documents supported endpoints, shared batch behavior, provider constraints, request counts, and JSONL results.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • ENTERPILOT/GoModel#343: Earlier Anthropic /v1/messages ingress work established related handler, routing, and endpoint-classification patterns.

Poem

A bunny found batches beneath the moon,
With msgbatch_ carrots in a neat little tune.
Create, list, cancel, delete with care,
JSONL results float through the air.
Providers hop in, stores tidy the way—
Anthropic’s batches now brighten the day!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: adding Anthropic Message Batches API support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/anthropic-message-batches

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@mintlify

mintlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟢 Ready View Preview Jul 17, 2026, 3:49 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@codecov-commenter

codecov-commenter commented Jul 17, 2026 •

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/anthropicapi/batch.go`:
- Around line 118-127: Update the customID validation in the batch request
processing flow to use trimming only for blank-value detection, while retaining
the original item.CustomID for deduplication, storage, and returned results.
Ensure IDs differing only by surrounding whitespace remain distinct and preserve
the caller’s exact correlation key.
- Around line 201-205: Update the ended-batch handling in the response
normalization flow around firstUnix and out.ProcessingStatus so it does not
derive ended_at from time.Now() on each retrieval. Use the provider’s persisted
transition timestamp when available, or a stable canonical fallback that remains
identical across responses, while preserving existing timestamp conversion
behavior.

In `@internal/providers/openai/compatible_provider_test.go`:
- Around line 239-308: Expand
TestCompatibleProvider_CreateBatch_UploadsInlineRequestsAsInputFile into a
table-driven test with separate cases for successful creation, /files failure,
and /batches failure. Configure the mock server per case, assert that
file-upload errors prevent any /batches request, and verify batch-creation
errors are returned after a successful upload while preserving the existing
success assertions.

In `@internal/providers/openai/compatible_provider.go`:
- Around line 438-446: Update the batch preparation and creation flow around
uploadInlineBatchInput to track the gateway-created temporary file in batch
metadata, then perform best-effort deletion whenever a subsequent /batches
operation fails, including the additional failure path around lines 473-484.
Preserve the original error while attempting cleanup, and do not delete
caller-provided InputFileID files.

In `@internal/server/messages_batch_handler_test.go`:
- Around line 50-53: Replace the map[string]any response decoding and subsequent
type assertions in the affected tests with Anthropic response structs or
dedicated typed test DTOs. Update the assertions to access typed fields
directly, including the response handling around the create, batch, and related
test cases, while preserving the existing validation behavior.

In `@internal/server/messages_batch_service.go`:
- Around line 139-143: Update the batch-results response flow to avoid calling
EncodeBatchResults or buffering the complete payload. Iterate through
result.Response and encode each result directly to the response writer as JSONL,
setting the application/x-jsonl content type and preserving appropriate error
handling for encoding or write failures.

In `@internal/server/messages_handler.go`:
- Around line 135-146: Update the `@Produce` annotation in MessagesBatchResults to
advertise application/x-jsonl instead of application/octet-stream, matching the
endpoint’s JSONL response while leaving the handler behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce144f5d-60f5-4ce0-ac34-d51c49fff8f2

📥 Commits

Reviewing files that changed from the base of the PR and between c328c78 and 41a1749.

📒 Files selected for processing (26)
  • docs/advanced/anthropic-messages-api.mdx
  • internal/anthropicapi/batch.go
  • internal/anthropicapi/batch_test.go
  • internal/batch/store.go
  • internal/batch/store_memory.go
  • internal/batch/store_memory_test.go
  • internal/batch/store_mongodb.go
  • internal/batch/store_postgresql.go
  • internal/batch/store_sqlite.go
  • internal/batch/store_sqlite_test.go
  • internal/core/batch.go
  • internal/core/endpoints.go
  • internal/core/endpoints_test.go
  • internal/core/interfaces.go
  • internal/core/semantic.go
  • internal/core/semantic_test.go
  • internal/gateway/batch_orchestrator.go
  • internal/providers/anthropic/batch.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/compatible_provider_test.go
  • internal/providers/router.go
  • internal/server/handlers_test.go
  • internal/server/http.go
  • internal/server/messages_batch_handler_test.go
  • internal/server/messages_batch_service.go
  • internal/server/messages_handler.go

Comment thread internal/anthropicapi/batch.go Outdated
Comment thread internal/anthropicapi/batch.go Outdated
Comment thread internal/providers/openai/compatible_provider_test.go Outdated
Comment thread internal/providers/openai/compatible_provider.go
Comment on lines +50 to +53
var created map[string]any
if err := json.Unmarshal(rec.Body.Bytes(), &created); err != nil {
t.Fatalf("decode create response: %v", err)
}

@coderabbitai coderabbitai Bot Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Decode API responses into typed structs.

These map[string]any assertions weaken schema checks and introduce panic-prone type assertions. Use the Anthropic response structs or dedicated typed test DTOs.

Based on learnings, API request and response payloads under internal/ should prefer strongly typed structs over map[string]any.

Also applies to: 63-75, 96-101, 111-119, 215-220, 267-272

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/server/messages_batch_handler_test.go` around lines 50 - 53, Replace
the map[string]any response decoding and subsequent type assertions in the
affected tests with Anthropic response structs or dedicated typed test DTOs.
Update the assertions to access typed fields directly, including the response
handling around the create, batch, and related test cases, while preserving the
existing validation behavior.

Source: Learnings

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping: map-based decoding is the established pattern across this package's handler tests (see handlers_test.go); switching one file would leave the suite inconsistent without changing coverage.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@SantiagoDePolonia, agreed. Keeping the established map-based decoding pattern in internal/server handler tests is reasonable here; a one-file typed-DTO conversion would be inconsistent without improving coverage. I’ll avoid raising this as a standalone concern in similar handler tests.

🐇


✏️ Learnings added
Learnt from: SantiagoDePolonia
Repo: ENTERPILOT/GoModel PR: 546
File: internal/server/messages_batch_handler_test.go:50-53
Timestamp: 2026-07-17T16:01:32.557Z
Learning: In the Go `internal/server` package, handler tests conventionally decode HTTP JSON responses into `map[string]any` and assert selected fields dynamically (for example, in `internal/server/handlers_test.go`). Do not request a one-off conversion to typed response DTOs in individual handler test files unless the package-wide convention is being changed or dynamic decoding causes a concrete test defect.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: SantiagoDePolonia
Repo: ENTERPILOT/GOModel PR: 33
File: internal/auditlog/auditlog_test.go:272-279
Timestamp: 2026-01-15T23:07:26.646Z
Learning: Go code guideline: Avoid using interface{} and map[string]interface{} for API request/response payload types. This should be restricted to public API surfaces and data payloads. It is acceptable to use interface{} in internal infrastructure packages (e.g., storage abstractions) only to break import cycles, and only when type assertions occur at initialization (not on every request) to minimize runtime type checks and improve readability. Apply this rule broadly to files under internal/ that deal with payload-like types, but not to internal components that are pure infrastructure or have runtime-per-request type assertions.

Learnt from: SantiagoDePolonia
Repo: ENTERPILOT/GOModel PR: 33
File: internal/auditlog/factory.go:112-143
Timestamp: 2026-01-15T23:07:37.652Z
Learning: Guideline: Do not use interface{} or map[string]interface{} for API request/response payload types. Prefer strongly-typed structs for API payload definitions to improve type safety, serialization, and documentation. Allow interface{} only in internal infrastructure code paths where pragmatic flexibility is necessary (e.g., to avoid import cycles or to handle highly dynamic internal contracts). In internal/auditlog/factory.go and similar non-API implementation files, applying this restriction is optional and should be evaluated on a case-by-case basis based on whether the type remains internal and does not define API boundary shapes.

Comment thread internal/server/messages_batch_service.go
Comment thread internal/server/messages_handler.go
@greptile-apps

greptile-apps Bot commented Jul 17, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

Safe to merge with low risk.

The updated code reuses the existing batch orchestrator and store paths, keeps provider-specific behavior behind interfaces, and includes focused tests for translation, lifecycle routes, pagination, results, delete behavior, and OpenAI inline uploads.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Ran the repository unit tests, handler tests, and provider tests to validate the code without invoking any live Anthropic or OpenAI providers.
  • Captured verbose test output and exit codes in evidence logs for review.
  • Verified a set of representative tests passed, including TestMessagesBatches_CreateGetList, TestMessagesBatches_Results, TestMessagesBatches_Cancel, TestMessagesBatches_Delete/ended_batch_deletes, TestMessagesBatches_Delete/in-progress_batch_is_rejected, TestMessagesBatches_InvalidCreateReturnsAnthropicError, TestToBatchRequest, TestFromBatchResponse, TestMemoryStoreDelete, TestSQLiteStoreDelete, and TestCompatibleProvider_CreateBatch_UploadsInlineRequestsAsInputFile.
  • Confirmed no live provider calls were attempted; validation relied solely on repository unit/handler/provider tests.

View all artifacts

T-Rex Ran code and verified through T-Rex

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant SDK as Anthropic SDK
    participant HTTP as /v1/messages/batches
    participant Edge as Anthropic dialect translator
    participant Orch as BatchOrchestrator
    participant Store as BatchStore
    participant Router as Provider Router
    participant Provider as Native batch provider

    SDK->>HTTP: POST create / GET / cancel / delete / results
    HTTP->>Edge: Decode Anthropic Message Batch payload or msgbatch ID
    Edge->>Orch: "Canonical batch request or batch_<uuid>"
    Orch->>Router: Resolve provider and native batch operation
    alt OpenAI-compatible inline requests
        Router->>Provider: "Upload JSONL file with purpose=batch"
        Provider-->>Router: input_file_id
        Router->>Provider: POST /batches with input_file_id
    else Native Message Batches provider
        Router->>Provider: Native message batch operation
    end
    Provider-->>Router: Native batch/result response
    Router-->>Orch: Canonical batch/result response
    Orch->>Store: Create / Update / Delete stored gateway batch
    Orch-->>Edge: Canonical batch/result response
    Edge-->>SDK: Anthropic message_batch or JSONL results
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant SDK as Anthropic SDK
    participant HTTP as /v1/messages/batches
    participant Edge as Anthropic dialect translator
    participant Orch as BatchOrchestrator
    participant Store as BatchStore
    participant Router as Provider Router
    participant Provider as Native batch provider

    SDK->>HTTP: POST create / GET / cancel / delete / results
    HTTP->>Edge: Decode Anthropic Message Batch payload or msgbatch ID
    Edge->>Orch: "Canonical batch request or batch_<uuid>"
    Orch->>Router: Resolve provider and native batch operation
    alt OpenAI-compatible inline requests
        Router->>Provider: "Upload JSONL file with purpose=batch"
        Provider-->>Router: input_file_id
        Router->>Provider: POST /batches with input_file_id
    else Native Message Batches provider
        Router->>Provider: Native message batch operation
    end
    Provider-->>Router: Native batch/result response
    Router-->>Orch: Canonical batch/result response
    Orch->>Store: Create / Update / Delete stored gateway batch
    Orch-->>Edge: Canonical batch/result response
    Edge-->>SDK: Anthropic message_batch or JSONL results
Loading

Reviews (1): Last reviewed commit: "feat(messages): add the Anthropic Messag..." | Re-trigger Greptile

- Preserve custom_id verbatim (trim only for blank detection) so results
  match the caller's correlation key byte-for-byte.
- Never fabricate ended_at at render time; it stays null unless the
  provider reported a transition timestamp.
- Best-effort delete the gateway-uploaded inline batch input file when
  the subsequent provider batch creation fails.
- Table-drive the inline-batch provider test with upload-failure and
  create-failure (cleanup) cases.
- Align the batch results swagger media type with application/x-jsonl.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mintlify

mintlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
gomodel 🟡 Building – Jul 17, 2026, 3:48 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/providers/openai/compatible_provider.go`:
- Around line 461-465: Update the cleanup path around DeleteFile in the
batch-create failure handling to use a detached context with a short timeout
instead of the already-canceled ctx, ensuring uploadedInputFileID is still
deleted after cancellation or timeout. Preserve the existing warning logging and
add a regression case covering cleanup when the request context is canceled.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab1fc192-dcbb-4e7c-a479-2e8af7ce9c81

📥 Commits

Reviewing files that changed from the base of the PR and between 41a1749 and 83f3878.

📒 Files selected for processing (5)
  • internal/anthropicapi/batch.go
  • internal/anthropicapi/batch_test.go
  • internal/providers/openai/compatible_provider.go
  • internal/providers/openai/compatible_provider_test.go
  • internal/server/messages_handler.go

Comment on lines +461 to +465
if uploadedInputFileID != "" {
if _, cleanupErr := p.DeleteFile(ctx, uploadedInputFileID); cleanupErr != nil {
slog.Warn("failed to clean up inline batch input file after batch create failure",
"provider", p.providerName, "file_id", uploadedInputFileID, "error", cleanupErr)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Detach file cleanup from the failed request context.

When /batches fails due to cancellation or timeout, ctx is already canceled, so DeleteFile immediately fails and leaves the uploaded request content orphaned. Use a detached context with a short cleanup timeout, and add a canceled-context regression case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/providers/openai/compatible_provider.go` around lines 461 - 465,
Update the cleanup path around DeleteFile in the batch-create failure handling
to use a detached context with a short timeout instead of the already-canceled
ctx, ensuring uploadedInputFileID is still deleted after cancellation or
timeout. Preserve the existing warning logging and add a regression case
covering cleanup when the request context is canceled.

Source: Coding guidelines

@SantiagoDePolonia
SantiagoDePolonia merged commit 0d12fc8 into main Jul 17, 2026
20 checks passed
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.

2 participants