Skip to content

Two open files designs disagree on where the bytes live, and neither references the other #1606

Description

@peteski22

Problem

Two live pieces of work answer "where do a file's bytes live" in opposite ways, and neither names the other in its description, its comments or its reviews.

#1185 (open since 2026-09-15, "support provider-neutral Files API support for hybrid mode", fixes #984). Its description says, in as many words: "File contents stay with the provider." It adds Anthropic and OpenAI Files operations through any-llm, selected by a header, with shared services enforcing account binding, ownership, quotas, retention, revocation and cleanup.

#1470 (the files epic) and #1366, whose direction 1 reads: "Otari's store is the source of truth for files. There is one files API, and where the bytes live is hidden behind it. A copy at a provider is a short-lived cache, made only when a provider-native feature needs one, with an expiry. A file a provider's code produces is copied into Otari's store."

That second answer is not a proposal: it is merged and released. #1366 shipped the surface, and #1517 ("copy the files a provider's code produces into Otari's store", for #1475) is on main. Both are in v0.7.0, v0.8.0 and v0.9.0.

So the repository currently holds one released answer and one open PR built on the other, with no written reconciliation. Every downstream decision inherits the ambiguity: retention that reaches every copy (#1487), provider-native files (#1488), giving a provider's sandbox the files a request attaches (#1481), and how a hybrid data plane moves bytes at all.

What makes them genuinely hard to merge

They are not two spellings of one idea. Provider behavior differs by direction:

  • An uploaded file on Anthropic is not downloadable. Only a file that code execution or skills created can be read back. So for uploads a provider copy is write-only: it cannot serve as a cache, and if Otari's store loses the bytes they are gone.
  • A generated file can be read back, but on a clock. An OpenAI code-interpreter container expires about 20 minutes after its last use and its data goes with it, so copying out is a race.
  • Anthropic files are scoped to the Anthropic workspace, not to an end user, and the Files API is not offered on Bedrock or Vertex, so the provider-native path has no equivalent on those routes.

Uploaded and generated files therefore have two different lifecycles, and the current design treats them as one.

That distinction has already shipped, which changes the cost of acting on it but not the answer. Otari is pre-1.0, so re-engineering a surface is a minor version bump rather than a deprecation window, and these releases are days old on a surface only standalone deployments serve. Shipped is not settled.

What this issue asks for

A written decision, referenced from both #1185 and #1470:

  1. Where the bytes live, per direction (uploaded, generated), rather than one answer for both.
  2. What a provider copy is: a cache with an expiry, or the record.
  3. How a hybrid data plane, which has no database and no store, moves bytes. This is the same question as Decide how a data plane reaches the code-execution backend: control-plane proxy, or a scoped grant #1603 asks for the code-execution backend: a control-plane proxy, or a scoped grant such as a presigned URL. FileStoragePort's s3 and fsspec adapters make the grant shape natural, and answering the two separately risks two different answers to one question.
  4. Whether feat(files): support provider-neutral Files API support for hybrid mode #1185 lands on top of the released answer, replaces it, or is withdrawn.

Not blocked on this

#1483 is a structural move of the code that already implements the released answer. It changes no behavior about where bytes live, and it leaves a thin route over a service rather than a 540-line route, which is the easier shape to reconcile into either way.

Sources for the provider facts above are Anthropic's and OpenAI's own API documentation, read 2026-09-22.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/apiAPI design and behaviorarea/backendBackend service implementationneeds-decisionRequires product/security decision

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions