Skip to content

Python: [Feature]: Define FIDES labeling for context-provider messages #9645

Closed

Description

Problem

ContextProvider instances are trusted framework plugins, but there is no first-class contract for attaching integrity and confidentiality labels to the messages they add to SessionContext. This makes it difficult for providers that wrap retrieved or remembered external data to integrate consistently with SecureAgentConfig without routing the data through a tool or implementing custom preprocessing.

The existing context-provider trust model remains valid: provider code itself is trusted and has access to the conversation and session state. The missing capability is a standard way for a trusted provider to describe the provenance and restrictions of the data it injects.

Use Case and Evidence

Memory, retrieval, and search providers may return a mixture of locally trusted records and externally sourced content. Applications using FIDES need to express, at message or content-item granularity, that provider-injected data is untrusted, private, or identity-scoped so that the cumulative context label and downstream tool policy reflect those restrictions.

Today providers can add ordinary Message objects, and SessionContext.extend_messages(...) adds source attribution, but SecureAgentConfig does not define an enforcement contract for provider-supplied labels. LabeledMessage exists, but it is not integrated into the context-provider assembly pipeline.

Desired Outcome

Define an opt-in, first-class provider-message labeling contract that allows trusted context providers to attach restriction-only integrity and confidentiality information. SecureAgentConfig should consume the labels after provider context has been assembled, preserve them through supported history and transport paths, and update the cumulative FIDES context label consistently.

The design should explicitly define defaults for unlabeled provider messages, how trusted local configuration may establish authority, and how caller- or remote-supplied labels are prevented from reducing restrictions.

Alternatives Considered

  • Continue treating all context providers as trusted and require each provider/application to manually sanitize or hide retrieved data. This remains the current documented model but does not provide consistent FIDES propagation.
  • Route provider data through FIDES-labeled tools. This works but changes provider architecture and can add unnecessary model/tool turns.
  • Use LabeledMessage directly. This lacks an integrated post-provider enforcement point and clear authenticity, serialization, and compatibility rules.

Proposed Direction

  • Add a provider-facing message/content labeling API, likely using the existing ContentLabel vocabulary.
  • Apply labels only after all providers have run, before the first model call.
  • Treat labels carried by ordinary messages as restriction-only unless trusted local configuration establishes them as authoritative.
  • Decide and document the compatibility default for unlabeled provider messages.
  • Preserve labels across history providers and supported transports.
  • Add coverage for mixed-trust provider output, forged label downgrades, provider ordering, streaming/non-streaming parity, and history restoration.

Scope and Non-Goals

In scope: provider-injected message/content labels and their interaction with SecureAgentConfig, history, and transports.

Non-goals: sandboxing untrusted provider code, changing the documented rule that ContextProvider implementations are trusted plugins, automatic semantic classification of retrieved text, or exposing hidden FIDES values to providers.

Language

Python

Contribution Intent

I can help with implementation or testing

Acknowledgements

  • I searched existing issues and did not find a duplicate.
  • I will wait for explicit maintainer agreement before starting implementation of a non-trivial change.

Activity

  1. eavanvalkenburg commented on Oct 26, 2026

    @eavanvalkenburg
    MemberAuthor

    /plan Design an opt-in, restriction-only provenance-label seam for non-history context-provider messages. Preserve the trusted-plugin boundary and restored history labels, prevent label weakening, and define persistence/transport behavior. Keep this follow-up separate from #9652; do not treat trusted Python providers as sandboxed untrusted code.

  2. eavanvalkenburg commented on Nov 5, 2026

    @eavanvalkenburg
    MemberAuthor

    /plan Design an opt-in, restriction-only provenance-label seam for non-history context-provider messages. Preserve the trusted-plugin boundary and restored history labels, prevent label weakening, and define persistence/transport behavior. Keep this follow-up separate from #9652; do not treat trusted Python providers as sandboxed untrusted code.

  3. github-actions commented on Nov 5, 2026

    @github-actions
    Contributor

    Summary

    You want a design for an opt-in way for trusted context providers (memory, retrieval, search) to say "this injected message is untrusted / private / identity-scoped", so FIDES (the framework's integrity/confidentiality label system) updates its running context label. Labels may only make things more restrictive. This is kept separate from #9652. Providers stay trusted plugins; this is not sandboxing. This is Python-only. I did not run code and did not look at open PRs.

    What the code does today

    • Provider messages carry no label. SessionContext.extend_messages copies each message and only adds an _attribution marker (source_id, source_type, optional origin_session_ids). See _sessions.py.
    • SecureAgentConfig is itself a context provider and its before_run only adds tools, instructions and middleware (security.py). It never reads other providers' messages.
    • Provider order is a real problem. Agent runs before_run for providers in list order (_agents.py). A provider listed after SecureAgentConfig adds messages it can't see. So there is currently no "after all providers" point inside this pipeline.
    • The context label only changes from tool results. It moves through _update_context_label in the tool middleware, using combine_labels (most-restrictive wins). The existing tool rule is the model to copy: embedded security_label values can only restrict a fallback, and full labels are accepted only from identity-stamped framework producers (_AUTHORITATIVE_SECURITY_LABEL).
    • LabeledMessage exists but is unused by the provider pipeline. Persisted/restored history messages carry additional_properties; _split_service_call_messages re-identifies provider messages via _attribution when splitting service-call messages.

    Recommendation

    Code changes are warranted, kept small, as an opt-in, experimental (FIDES feature) addition, plus documentation of the trust model. Existing workarounds (routing data through labeled tools, manual sanitizing) work but force extra tool turns and don't update the context label consistently, so they are not an adequate general answer. Because this touches persistence and transports, I suggest an ADR first (per docs/decisions/) and maintainer agreement before coding, as you noted.

    Proposed plan

    1. Label carrier (restriction-only). Let providers pass an optional label through extend_messages(..., label=ContentLabel), stored under a reserved key in additional_properties (e.g. security_label, same name the tool path uses). No new trust: any value there is treated as a claim that can only restrict.

    2. Single enforcement point after all providers. Apply labels in one place that runs after the provider loop finishes and before the first model call (in Agent's context assembly, or a chat middleware that SecureAgentConfig registers). Don't rely on SecureAgentConfig.before_run ordering. Only active when SecureAgentConfig is configured; otherwise behavior is unchanged.

    3. No weakening. Effective label for a message = combine_labels(default_for_unlabeled, claimed_label) per message/content item. Never replace a stricter baseline with a weaker claim. Confidentiality principals (identity scope) follow the existing PRINCIPAL_METADATA_KEY handling.

    4. Defaults for unlabeled provider messages. Decision needed: keep today's behavior (no change to cumulative label) as the compatible default, with an opt-in config such as unlabeled_provider_integrity=UNTRUSTED and a per-source_id mapping set by trusted local configuration (this is the only way to establish a stronger-than-default claim such as "trusted"). Default must be fail-compatible; I suggest not raising trust from message data ever.

    5. Cumulative label. Fold each effective label into the session's context label once, at assembly time, and persist it in the existing security session state, so streaming and non-streaming runs behave identically.

    6. Persistence and transport.

      • Restored history: labels already stored on history messages are kept and re-folded; a provider cannot relabel history messages (apply the seam only to non-history source_ids).
      • Stored labels are re-validated on load, like durable variable labels; malformed data fails closed to the most restrictive label.
      • Transports (AG-UI etc.) treat incoming labels as untrusted claims: restrict-only, never trusted/authoritative (compare existing AG-UI tests for context_label state).
    7. Docs. State clearly that providers remain trusted code, that labels are provenance metadata not a sandbox, and that provider-injected hidden values aren't exposed to providers.

    Tests

    • Mixed-trust output from one provider and from several; provider order before and after SecureAgentConfig.
    • Forged downgrade attempts (message claims "trusted"/"public") leave the label unchanged.
    • Streaming vs non-streaming parity; session save/restore; history messages keep restored labels.
    • Transport round trip with a tampered label; unlabeled default and per-source override.

    Done when

    Labeled provider messages raise the context label before the first model call, no input can lower it, and unconfigured agents behave exactly as today.

    Open questions I'd like settled in the ADR

    • Is "unlabeled = no change" acceptable, or should FIDES-enabled agents default unlabeled provider data to untrusted?
    • Message-level vs content-item-level granularity in the first version?

    No changes have been made; this is a proposal.

    Generated by Issue Planning for #9645 · copilot · auto · ~48 AIC · ⌖ ~1 AIC · ⊞ 4.8K · ◷

  4. eavanvalkenburg commented on Nov 13, 2026

    @eavanvalkenburg
    MemberAuthor

    Fixed in #9876

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

Metadata

Metadata

Labels

pythonUsage: [Issues, PRs], Target: Python

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions