Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
pip install -c constraints.txt -r requirements-dev.txt
- name: Run unit tests
run: |
PYTHONPATH=. pytest tests/test_unit.py tests/test_worker_fallback.py tests/test_supporting_components.py tests/test_resource_bindings.py --cov=execution_engine --cov-report=term-missing --cov-report=xml
PYTHONPATH=. pytest tests/test_unit.py tests/test_worker_fallback.py tests/test_supporting_components.py --cov=execution_engine --cov-report=term-missing --cov-report=xml
python3 scripts/check-contracts.py
python3 scripts/check-harness.py
- name: Upload coverage artifact
Expand Down
2 changes: 1 addition & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ tasks:
desc: Run unit tests
cmds:
- task python:check
- "PYTHONPATH=. {{.PYTHON}} -m pytest tests/test_unit.py tests/test_worker_fallback.py tests/test_supporting_components.py tests/test_tool_context.py tests/test_remediation.py tests/test_worker_approval_resume.py tests/test_resource_bindings.py tests/test_transcript_contract.py tests/test_react_transcript.py tests/test_keyless_eval_manifest.py"
- "PYTHONPATH=. {{.PYTHON}} -m pytest tests/test_unit.py tests/test_worker_fallback.py tests/test_supporting_components.py tests/test_tool_context.py tests/test_remediation.py tests/test_worker_approval_resume.py tests/test_transcript_contract.py tests/test_react_transcript.py tests/test_keyless_eval_manifest.py"

keyless-eval:
desc: Measure provider-native agent scenarios without credentials or TCP connections
Expand Down
1 change: 0 additions & 1 deletion constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ uvicorn==0.46.0
httpx==0.28.1
pydantic==2.13.4
pydantic-settings==2.14.2
rfc8785==0.1.4
tenacity==9.1.4
anyio==4.13.0
prometheus-client==0.25.0
Expand Down
2 changes: 0 additions & 2 deletions docs/contracts/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@
"assistant?.{targetType?,instructions}",
"policy.{max_runtime_ms,max_output_tokens,budget_cents,max_steps,max_tool_calls,max_duplicate_tool_calls}",
"context.{endpoint,max_context_tokens}",
"resources.{prompt_digest,binding_digest,resolved_at,bindings[].{binding_id,type,resource_id,provider,provider_version,workspace_id,label_snapshot,source,operations,context_mode,provider_data?}}",
"llm.{provider,model,temperature,mode,reasoning.{summary_mode,effort},gateway.{url,token,request_timeout_ms}}",
"tools.{tool_registry_version,allowed_tools,allowed_tool_refs[].{server_id,tool_name},native_tools,platform_functions[].{id,model_alias},tool_specs[].{server_id?,tool_ref?},referenced_tools[].{name,label,server_id?,tool_name?},write_unavailable_reason?,gateway.{url,token},confirmation_required_for_write,approval_timeout_seconds}",
"skills?.{contract_version,entries[].{ref,skill_id,name,description,file_count,total_bytes},referenced_refs[],load_endpoint}",
"routing",
"tracing"
],
"contextFields": ["messages", "summaries", "attachments", "target_insights.retrieval_status", "target_insights.snippets[]"],
"promptResourceIntegrity": "The execution engine rejects duplicate bindings, oversized or malformed claims, and any binding array whose canonical SHA-256 digest differs from resources.binding_digest.",
"eventFrameFields": ["schema_version", "run_id", "seq", "ts", "type", "payload"],
"approvalRequestFields": ["toolCallId", "toolName", "toolRef.{serverId,toolName}", "summary?", "arguments", "continuation?"],
"approvalExecutionStartedResponseFields": ["approval", "approvalReceipt"],
Expand Down
82 changes: 0 additions & 82 deletions execution_engine/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
"""Pydantic models for API requests, responses, and internal data structures."""

import hashlib
from datetime import UTC, datetime
from typing import Annotated, Any, Dict, List, Literal, Optional, Union

import rfc8785
from pydantic import BaseModel, ConfigDict, Field, RootModel, model_validator

from execution_engine.examples import (
Expand Down Expand Up @@ -172,76 +170,6 @@ class ContextConfig(BaseModel):
max_context_tokens: int


class ResourceBinding(BaseModel):
"""An exact prompt resource binding frozen by the control plane."""

binding_id: str
type: str
resource_id: str
provider: str
provider_version: str
workspace_id: str
label_snapshot: str
source: Literal["explicit", "implicit", "trigger"]
operations: List[str]
context_mode: Literal["inline", "tool", "routing_only"]
provider_data: Optional[Dict[str, Any]] = None

@model_validator(mode="after")
def validate_operations(self):
if not self.operations or len(self.operations) > 64:
raise ValueError("resource binding operations must contain 1 to 64 entries")
if len(self.operations) != len(set(self.operations)) or any(
not operation.strip() for operation in self.operations
):
raise ValueError("resource binding operations must be unique and non-empty")
return self

model_config = ConfigDict(extra="forbid", strict=True)


class ResourceConfig(BaseModel):
"""Prompt and binding integrity metadata for a Workflow run."""

prompt_digest: str
binding_digest: str
resolved_at: str
bindings: List[ResourceBinding] = Field(default_factory=list, max_length=64)

@model_validator(mode="after")
def validate_integrity_metadata(self):
if len(self.prompt_digest) != 64 or len(self.binding_digest) != 64:
raise ValueError("resource digests must be SHA-256 hex strings")
if any(character not in "0123456789abcdef" for character in self.prompt_digest + self.binding_digest):
raise ValueError("resource digests must be lowercase SHA-256 hex strings")
binding_ids = [binding.binding_id for binding in self.bindings]
if len(binding_ids) != len(set(binding_ids)):
raise ValueError("resource binding IDs must be unique")
canonical = []
for binding in self.bindings:
value = {
"bindingId": binding.binding_id,
"type": binding.type,
"resourceId": binding.resource_id,
"provider": binding.provider,
"providerVersion": binding.provider_version,
"workspaceId": binding.workspace_id,
"labelSnapshot": binding.label_snapshot,
"source": binding.source,
"operations": binding.operations,
"contextMode": binding.context_mode,
}
if binding.provider_data is not None:
value["providerData"] = binding.provider_data
canonical.append(value)
actual = hashlib.sha256(rfc8785.dumps(canonical)).hexdigest()
if actual != self.binding_digest:
raise ValueError("binding_digest does not match bindings")
return self

model_config = ConfigDict(extra="forbid", strict=True)


class GatewayConfig(BaseModel):
"""Configuration for the Execution Gateway."""

Expand Down Expand Up @@ -339,22 +267,13 @@ class ExecutionSnapshot(BaseModel):
scope: Scope
policy: Policy
context: ContextConfig
resources: Optional[ResourceConfig] = None
llm: LLMConfig

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep accepting retired resources during mixed-version rollouts

When an older control-plane replica or a rollback still returns a version-2 bootstrap containing the formerly valid resources field—even resources: nullExecutionSnapshot.model_validate() now rejects it because the model still declares contract_version: Literal[2] but has extra="forbid"; OrchestratorClient.bootstrap() then propagates the validation error and the worker terminates the run as BOOTSTRAP_FAILED. Preserve a deprecated ignored field until every producer is upgraded, or introduce a new contract version with explicit rollout ordering rather than making the existing version incompatible.

AGENTS.md reference: AGENTS.md:L42-L42

Useful? React with 👍 / 👎.

tools: ToolConfig
assistant: Optional[AssistantConfig] = None
skills: Optional[SkillConfig] = None
routing: Dict[str, Any]
tracing: Dict[str, Any]

@model_validator(mode="after")
def validate_resource_scope(self):
if self.resources and any(
binding.workspace_id != self.scope.workspace_id for binding in self.resources.bindings
):
raise ValueError("resource bindings must match the run workspace")
return self

model_config = ConfigDict(extra="forbid")


Expand Down Expand Up @@ -395,7 +314,6 @@ class ContextPackage(BaseModel):
messages: List[Message]
summaries: List[Any] = []
attachments: List[Any] = []
resources: List[Dict[str, Any]] = []
target_insights: TargetInsightsContext | None = None


Expand Down
6 changes: 0 additions & 6 deletions requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,6 @@ redis==7.4.0 \
# via
# -c constraints.txt
# -r requirements.txt
rfc8785==0.1.4 \
--hash=sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48 \
--hash=sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da
# via
# -c constraints.txt
# -r requirements.txt
starlette==1.3.1 \
--hash=sha256:05d0213193f2fbaae60e2ecb593b4add4262ad4e46536b54abe36f11a71724e0 \
--hash=sha256:c7372aae11c3c3f26a42df7bd626cec2f47d03483d261d369516a615a53714c6
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ tenacity
anyio
prometheus-client
redis
rfc8785==0.1.4
23 changes: 0 additions & 23 deletions tests/fixtures/resource-binding-digest-conformance.json

This file was deleted.

65 changes: 0 additions & 65 deletions tests/test_resource_bindings.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ async def test_coordination_functions_reject_unknown_arguments_before_orchestrat
{
"capabilityId": "infrastructure.diagnostics.read",
"taskPrompt": "Inspect the infrastructure",
"resourceBinding": {"resourceId": "resource-1"},
"unexpected": True,
},
call_id="call-delegate-1",
)
Expand Down
Loading