Skip to content

Allow a QuickApp to narrow which MIME types the lazy_on_demand strategy accepts #545

Description

@andrii-novikov

QuickApps version

0.11.1

What is the problem this feature will solve?

Under attachment_strategy: lazy_on_demand, the only gate on what the orchestrator will load is the orchestrator deployment's input_attachment_types, read from DIAL Core (OrchestratorCapabilities.orchestrator_accepts_mime_type, src/quickapp/core/agent/orchestrator_capabilities.py:26). It is consulted in four places — _gating.should_enable_get_content_tool, _GetContentTool, _GetContentKeepPolicy, _AttachmentGetContentInjector — and a QuickApp has no way to narrow it.

That deployment is shared across every app pointing at it, so the app author cannot fix it locally either.

Two consequences:

  1. Declared support is not always real support. Deployments are routinely registered with an optimistic or copy-pasted input_attachment_types, including the */* catch-all. matches_type short-circuits to True on ALL_MIME_TYPES (src/quickapp/common/utils.py), so in that case there is effectively no gate at all: the model is told it may load anything, calls internal_attachments_get_content on a file the model cannot actually read, and the failure surfaces downstream from the adapter instead of as a clean refusal.
  2. No way to scope an app below its model. An app whose orchestrator supports images and PDFs may still want only images to reach the model — for cost, for prompt hygiene, or because the app's whole job is visual. Today that is not expressible.

The tool description makes this user-visible: render_get_content_tool_config advertises the deployment's list to the model ("Accepted MIME types: …"), so a wrong */* is actively taught to the model as an allowlist.

What is the feature you are proposing to solve the problem?

Add an optional per-app MIME allowlist to the strategy config:

class LazyOnDemandAttachmentStrategy(BaseModel):
    type: Literal["lazy_on_demand"] = ...
    accepted_types: list[str] | None = Field(
        default=None,
        description=(
            "Narrows which MIME types the orchestrator will load for this app, within "
            "what the deployment's input_attachment_types allow. null (default) accepts "
            "everything the deployment declares."
        ),
    )
{
  "orchestrator": {
    "attachment_strategy": { "type": "lazy_on_demand", "accepted_types": ["image/*"] }
  }
}

Shape of the change:

  • Enforce at one choke pointOrchestratorCapabilities.orchestrator_accepts_mime_type. All four consumers already read through it, and it is constructed in a single place (_orchestrator_deployment_initializer.py:38), so no call site needs to change.
  • Conjunction, not intersection — require a MIME to match both the deployment list and the app list, rather than computing an intersected pattern set (image/*image/png is fiddly, and worse with */*). The deployment stays a hard cap that an app can only narrow, never widen.
  • Advertise the narrowed list — pass the app list to render_get_content_tool_config when set, so the model is told the real allowlist.
  • Run make dump_app_schema; a config-load warning when accepted_types contains a type the deployment does not declare would help catch typos.

Scope note: this narrows the fetch path app-wide — it applies to user attachments and admin contexts too, not just to one source. "User PDFs readable, but tool outputs images only" is not expressible with this field; that is the per-tool propagate_types_to_orchestrator from #542.

The new field will also need an editor surface (separate ai-dial-chat issue).

What alternatives have you considered?

  • Fix input_attachment_types on the deployment in DIAL Core. Correct where the declaration is simply wrong, but the deployment is shared, so it cannot express a per-app restriction, and app authors often cannot change it.
  • Per-tool propagate_types_to_orchestrator (Allow tools to pass produced attachments (e.g. rendered images) to the orchestrator #542). Governs the push path (what a tool may hand over), not the fetch path (what the model may pull). Complementary, not a substitute.
  • Hardcode a conservative allowlist in the strategy. No config surface, but it would break apps that legitimately rely on the deployment's full set.

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions