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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Agents API sits between tool/action discovery and product-specific automation. I
- Product CLI commands beyond generic substrate needs.
- Public REST controllers in v1 unless they are separately designed.
- Product runner adapters that assemble prompts, choose concrete tools, materialize storage, or decide product policy.
- Concrete runtime package materialization, package source checkout, sandbox provisioning, provider mapping, run polling, or evidence artifact upload. The package run contract only defines the request/result envelope and dispatcher seam.
- Concrete runtime package materialization, package source checkout, delegated-runtime provisioning, provider mapping, run polling, or evidence artifact upload. The package run contract only defines the request/result envelope and dispatcher seam.
- Concrete tool execution adapters, prompt assembly policy, or product storage/materialization policy.
- Product-specific consent UX, support routing, escalation targets, or transcript-sharing policy.
- Concrete memory retrieval, file projection, convention-path writing, or filesystem layout adapters.
Expand Down
2 changes: 2 additions & 0 deletions docs/runtime-and-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,8 @@ The substrate treats `runtime` as a JSON-friendly associative array. It preserve

Delegated runtime consumers should advertise runtime-local tools with `capability_scope: runtime_local` and `environment: runtime_local`. Control-plane tools such as repository mutation, deployment, approval, or parent orchestration actions should use `capability_scope: control_plane` and stay out of runtime-local declarations. Agents API records and propagates this vocabulary; hosts still own the concrete allow/deny policy and execution adapter.

Runtime tool policy envelopes use the canonical schema `agents-api/runtime-tool-policy/v1`. Each projected tool emits neutral top-level `environment` and `capability_scope` fields alongside the nested `runtime` metadata. The compatibility fields `execution_location` and `transport_visibility` may still appear for older consumers; treat them as legacy aliases and prefer `runtime_local`/`control_plane` values from the canonical fields. Policy entries list those aliases in `legacy_fields` when emitted.

Delegated runtimes can also resolve an execution principal with `WP_Agent_Execution_Principal::runtime()`. The helper produces a non-user runtime principal with `auth_source: runtime`, `request_context: runtime`, a host-owned runtime `audience_id`, and an isolated runtime conversation owner key. Hosts remain responsible for attesting the runtime, choosing the owner key, supplying any `runtime_type` claim, and enforcing authorization policy.

When the conversation loop mediates tool calls, declaration runtime metadata is propagated into the normalized tool result and exposed on the corresponding `tool_execution_results[]` entry:
Expand Down
2 changes: 1 addition & 1 deletion src/Channels/register-agents-chat-ability.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ function agents_chat_input_schema(): array {
),
'tool_policy' => array(
'type' => array( 'object', 'null' ),
'description' => 'Optional caller-owned tool policy for this turn. Runtimes may use this to narrow tool visibility for peer-agent or sandbox invocations.',
'description' => 'Optional caller-owned tool policy for this turn. Runtimes may use this to narrow tool visibility for peer-agent or delegated-runtime invocations.',
'properties' => array(
'mode' => array(
'type' => 'string',
Expand Down
7 changes: 6 additions & 1 deletion src/Tools/class-wp-agent-runtime-tool-policy.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,19 @@ public static function fromTools( array $tools, array $context = array() ): arra
continue;
}

$runtime = self::runtimeMetadata( $tool );
$runtime = self::runtimeMetadata( $tool );
$environment = $runtime[ WP_Agent_Tool_Declaration::RUNTIME_ENVIRONMENT ];
$capability_scope = $runtime[ WP_Agent_Tool_Declaration::RUNTIME_CAPABILITY_SCOPE ];
$policy_tool = array(
'id' => $id,
'runtime_tool_id' => self::runtimeToolId( $id, $tool ),
'allowed' => self::isRuntimeLocal( $runtime ),
'environment' => $environment,
'capability_scope' => $capability_scope,
'runtime' => $runtime,
'execution_location' => self::legacyExecutionLocation( $runtime ),
'transport_visibility' => self::legacyTransportVisibility( $runtime ),
'legacy_fields' => array( 'execution_location', 'transport_visibility' ),
);
if ( is_string( $tool['source'] ?? null ) && '' !== $tool['source'] ) {
$policy_tool['source'] = $tool['source'];
Expand Down
6 changes: 3 additions & 3 deletions tests/agents-chat-ability-smoke.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ function smoke_assert( $expected, $actual, string $name, array &$failures, int &
smoke_reset_chat_filters();
$runtime_principal = AgentsAPI\AI\WP_Agent_Execution_Principal::runtime(
'runtime-session-1',
'sandbox-agent',
'runtime-local-agent',
array( 'source' => 'example-runtime' ),
'workspace:demo',
'example-runtime-cli',
Expand All @@ -199,7 +199,7 @@ function smoke_assert( $expected, $actual, string $name, array &$failures, int &
$captured_principal = is_array( $input['principal'] ?? null ) ? $input['principal'] : array();
return array( 'session_id' => 'runtime-s-1', 'reply' => 'runtime ok', 'completed' => true );
} );
$runtime_result = agents_chat_dispatch( array( 'agent' => 'sandbox-agent', 'message' => 'go', 'principal' => $runtime_principal ) );
$runtime_result = agents_chat_dispatch( array( 'agent' => 'runtime-local-agent', 'message' => 'go', 'principal' => $runtime_principal ) );
smoke_assert( 'runtime ok', $runtime_result['reply'] ?? null, 'runtime_principal_dispatch_succeeds', $failures, $passes );
smoke_assert( AgentsAPI\AI\WP_Agent_Execution_Principal::AUTH_SOURCE_RUNTIME, $captured_principal['auth_source'] ?? null, 'runtime_principal_normalized_for_handler', $failures, $passes );
smoke_assert( array( 'type' => AgentsAPI\AI\WP_Agent_Execution_Principal::OWNER_TYPE_RUNTIME, 'key' => 'runtime-session-1' ), AgentsAPI\AI\WP_Agent_Execution_Principal::from_array( $captured_principal )->conversation_owner(), 'runtime_principal_preserves_owner', $failures, $passes );
Expand All @@ -211,7 +211,7 @@ function smoke_assert( $expected, $actual, string $name, array &$failures, int &
}, 10, 2 );
smoke_assert( true, agents_chat_permission( array( 'principal' => $runtime_principal ) ), 'runtime_principal_permission_filter_allows', $failures, $passes );

$invalid_principal_result = agents_chat_dispatch( array( 'agent' => 'sandbox-agent', 'message' => 'go', 'principal' => 'not-object' ) );
$invalid_principal_result = agents_chat_dispatch( array( 'agent' => 'runtime-local-agent', 'message' => 'go', 'principal' => 'not-object' ) );
smoke_assert( true, $invalid_principal_result instanceof WP_Error, 'invalid_principal_returns_wp_error', $failures, $passes );
smoke_assert( 'agents_chat_invalid_principal', $invalid_principal_result->get_error_code(), 'invalid_principal_error_code', $failures, $passes );

Expand Down
2 changes: 1 addition & 1 deletion tests/run-result-envelope-smoke.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
'artifact_refs' => array( array( 'type' => 'package', 'label' => 'bundle' ) ),
'evidence_refs' => array( array( 'type' => 'trace', 'label' => 'trace' ) ),
'replay' => array( 'recipe' => 'site' ),
'metadata' => array( 'runtime' => 'codebox' ),
'metadata' => array( 'runtime' => 'runtime_local' ),
)
);
$runtime_array = $runtime->to_array();
Expand Down
7 changes: 5 additions & 2 deletions tests/runtime-tool-policy-smoke.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,14 @@

agents_api_smoke_assert_equals( true, $by_id['filesystem-write']['allowed'] ?? false, 'runtime-local tool is allowed', $failures, $passes );
agents_api_smoke_assert_equals( 'filesystem_write', $by_id['filesystem-write']['runtime_tool_id'] ?? '', 'runtime tool id can be declared explicitly', $failures, $passes );
agents_api_smoke_assert_equals( WP_Agent_Tool_Declaration::ENVIRONMENT_RUNTIME_LOCAL, $by_id['filesystem-write'][ WP_Agent_Tool_Declaration::RUNTIME_ENVIRONMENT ] ?? '', 'runtime-local tool emits canonical execution environment', $failures, $passes );
agents_api_smoke_assert_equals( WP_Agent_Tool_Declaration::CAPABILITY_SCOPE_RUNTIME_LOCAL, $by_id['filesystem-write'][ WP_Agent_Tool_Declaration::RUNTIME_CAPABILITY_SCOPE ] ?? '', 'runtime-local tool emits canonical capability scope', $failures, $passes );
agents_api_smoke_assert_equals( WP_Agent_Tool_Declaration::ENVIRONMENT_RUNTIME_LOCAL, $by_id['filesystem-write']['runtime'][ WP_Agent_Tool_Declaration::RUNTIME_ENVIRONMENT ] ?? '', 'runtime-local tool records execution environment', $failures, $passes );
agents_api_smoke_assert_equals( 'sandbox', $by_id['filesystem-write']['execution_location'] ?? '', 'runtime-local tool projects legacy sandbox location for consumers', $failures, $passes );
agents_api_smoke_assert_equals( array( 'execution_location', 'transport_visibility' ), $by_id['filesystem-write']['legacy_fields'] ?? array(), 'runtime-local tool marks compatibility-only fields as legacy', $failures, $passes );

agents_api_smoke_assert_equals( false, $by_id['control-plane/workspace-git-push']['allowed'] ?? true, 'control-plane tool is denied to runtime-local agent', $failures, $passes );
agents_api_smoke_assert_equals( 'parent', $by_id['control-plane/workspace-git-push']['transport_visibility'] ?? '', 'control-plane tool projects parent visibility', $failures, $passes );
agents_api_smoke_assert_equals( WP_Agent_Tool_Declaration::ENVIRONMENT_CONTROL_PLANE, $by_id['control-plane/workspace-git-push'][ WP_Agent_Tool_Declaration::RUNTIME_ENVIRONMENT ] ?? '', 'control-plane tool emits canonical execution environment', $failures, $passes );
agents_api_smoke_assert_equals( WP_Agent_Tool_Declaration::CAPABILITY_SCOPE_CONTROL_PLANE, $by_id['control-plane/workspace-git-push'][ WP_Agent_Tool_Declaration::RUNTIME_CAPABILITY_SCOPE ] ?? '', 'control-plane tool emits canonical capability scope', $failures, $passes );
agents_api_smoke_assert_equals( 'control_plane_workspace_read', $by_id['control-plane/workspace-read']['runtime_tool_id'] ?? '', 'runtime tool id defaults from tool name', $failures, $passes );
agents_api_smoke_assert_equals( false, $by_id['control-plane/workspace-read']['allowed'] ?? true, 'tools without runtime metadata default closed', $failures, $passes );

Expand Down