Skip to content

policy-engine: AgentControl::new(runtime) leaves parts=None, making with_telemetry a no-op and revalidating against Limits::default #3941

Description

@MohammadHaroonAbuomar

policy-engine/sdk/rust/src/host/mod.rs: constructing AgentControl from a Runtime leaves parts=None, so with_telemetry(sink) silently does nothing, a failed Runtime::with_telemetry_perf_and_limits is swallowed, evaluate_intervention_point revalidates transformed snapshots against Limits::default() rather than the configured limits, and the removed-field check added in #3940 is bypassed for hand-built runtimes. Either populate parts from the runtime or reject construction paths that cannot.

Found in the group review of the policy-engine retarget (#3939) and deferred from the follow-up (#3940).

Activity

  1. chopmob-cloud commented on Sep 20, 2026

    @chopmob-cloud
    Contributor

    On agent-control-spec =0.4.0-alpha.3, AgentControl::new(runtime) cannot populate parts from the runtime: Runtime stores annotations and limits as private fields with no public accessors (only manifest(), policy_dispatcher(), perf_telemetry() are exposed), and EvaluationResult carries only verdict/policy_input. So new receives an already-built Runtime it cannot read those back from. The working constructor only captures parts because it builds the runtime itself.

    The fail-open is confirmed: with parts = None, evaluate_intervention_point revalidates a Transform snapshot against Limits::default() (via unwrap_or_default()), so a caller who tightened e.g. max_snapshot_bytes gets the transformed snapshot checked against the looser default.

    Given that, the options are: (A) fail closed on Transform when parts is None (smallest, non-breaking; also rejects transforms for callers who legitimately used default limits; does not fix the with_telemetry no-op); (B) A plus #[deprecated] on new and a parts-aware constructor so telemetry/limits work correctly (non-breaking, matches "reject construction paths that cannot"); (C) make new fallible / require limits+annotations (breaking); (D) add Runtime accessors upstream in agent-control-spec and bump the pin, then populate parts in new (your option 1, done properly, but a separate crate + coordinated release).

    I would lean (B), with (D) as the eventual full fix. Which direction do you prefer? Happy to open the PR once you confirm, so it does not fight your intended shape.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions