refactor(agent-runner): align config with agent semantics

This commit is contained in:
huanghuoguoguo
2026-06-02 17:43:44 +08:00
parent d0383e146e
commit f2153f736c
23 changed files with 94 additions and 126 deletions

View File

@@ -25,7 +25,7 @@ class ConfigMigration:
Responsibilities:
- Resolve runner ID from new ai.runner.id or old ai.runner.runner
- Map old built-in runner names to official plugin runner IDs
- Extract runtime runner config from ai.runner_config
- Extract current Agent/runner config from ai.runner_config
- Migrate old ai.<runner-name> blocks into ai.runner_config
"""
@@ -74,7 +74,7 @@ class ConfigMigration:
pipeline_config: dict[str, typing.Any],
runner_id: str,
) -> dict[str, typing.Any]:
"""Resolve runner binding configuration from pipeline configuration.
"""Resolve Agent/runner configuration from pipeline configuration.
Runtime code should only read the migrated format. Legacy
ai.<runner-name> blocks are handled by migration helpers, not by the
@@ -114,9 +114,6 @@ class ConfigMigration:
if old_runner_name:
old_config = ai_config.get(old_runner_name, {})
if old_config:
old_config = dict(old_config)
if runner_id == OLD_RUNNER_TO_PLUGIN_RUNNER_ID['local-agent']:
old_config.pop('max-round', None)
return ConfigMigration.normalize_runner_config_for_migration(runner_id, old_config)
return {}
@@ -126,7 +123,7 @@ class ConfigMigration:
runner_id: str,
runner_config: dict[str, typing.Any],
) -> dict[str, typing.Any]:
"""Normalize released legacy runner config before storing binding config.
"""Normalize released legacy runner config before storing Agent/runner config.
Runtime code should not carry aliases. This helper is intentionally used
only by config migration so AgentRunner implementations can consume the

View File

@@ -22,7 +22,7 @@ class AgentTrigger(typing.TypedDict):
"""Agent trigger information."""
type: str
source: str # 'pipeline' or 'event_router'
source: str
timestamp: int | None
@@ -37,7 +37,6 @@ class ConversationContext(typing.TypedDict):
bot_id: str | None
workspace_id: str | None
session_id: str | None
pipeline_uuid: str | None
class AgentInput(typing.TypedDict):
@@ -128,8 +127,9 @@ class AgentRunContextPayload(typing.TypedDict):
Protocol v1 structure - matches SDK AgentRunContext.
Note: The 'config' field contains the binding config from ai.runner_config[runner_id],
which is Pipeline's configuration for this specific runner binding (not plugin instance config).
Note: The 'config' field contains the current Agent/runner config
from ai.runner_config[runner_id] while Pipeline remains the temporary
configuration container. It is not plugin instance config.
"""
run_id: str
@@ -144,9 +144,9 @@ class AgentRunContextPayload(typing.TypedDict):
context: dict[str, typing.Any] # ContextAccess - REQUIRED for Protocol v1
state: AgentRunState
runtime: AgentRuntimeContext
config: dict[str, typing.Any] # Binding config from ai.runner_config[runner_id]
config: dict[str, typing.Any] # Agent/runner config from ai.runner_config[runner_id]
bootstrap: dict[str, typing.Any] | None # Optional bootstrap context
adapter: dict[str, typing.Any] | None # Pipeline adapter context
adapter: dict[str, typing.Any] | None # Entry adapter context
metadata: dict[str, typing.Any] # Additional metadata
@@ -160,7 +160,7 @@ class AgentRunContextBuilder:
- Build input from event
- Build state snapshot from PersistentStateStore
- Build runtime context with host info, trace_id, deadline
- Set config from runner binding configuration.
- Set config from current Agent/runner configuration.
Pipeline Query adaptation belongs to PipelineAdapter, not this builder.
"""
@@ -184,7 +184,7 @@ class AgentRunContextBuilder:
Args:
event: Event envelope
binding: Agent binding configuration
binding: Agent binding
descriptor: Runner descriptor
resources: Built resources
@@ -205,7 +205,7 @@ class AgentRunContextBuilder:
conversation: ConversationContext | None = None
if event.conversation_id:
conversation = {
'session_id': None, # Pipeline adapter field
'session_id': None,
'conversation_id': event.conversation_id,
'thread_id': event.thread_id,
'launcher_type': None, # Will be filled from actor/subject if needed
@@ -213,7 +213,6 @@ class AgentRunContextBuilder:
'sender_id': event.actor.actor_id if event.actor else None,
'bot_id': event.bot_id,
'workspace_id': event.workspace_id,
'pipeline_uuid': binding.pipeline_uuid, # Pipeline adapter field
}
# Build event context (Protocol v1 event-first)
@@ -277,7 +276,7 @@ class AgentRunContextBuilder:
'model_context_window_tokens': None,
# TODO(model-info): populate model_context_window_tokens after
# LiteLLM/model metadata lands. Runners fall back to their
# binding config until Host can provide the real window.
# ctx.config until Host can provide the real window.
},
}
@@ -295,7 +294,6 @@ class AgentRunContextBuilder:
# Build adapter context (empty for event-first)
adapter_context = {
'query_id': None,
'pipeline_uuid': binding.pipeline_uuid,
'extra': {},
}

View File

@@ -15,7 +15,7 @@ class RunnerNotFoundError(AgentRunnerError):
class RunnerNotAuthorizedError(AgentRunnerError):
"""Runner not authorized for this pipeline."""
"""Runner not authorized for this binding."""
def __init__(self, runner_id: str, bound_plugins: list[str] | None):
self.runner_id = runner_id
self.bound_plugins = bound_plugins
@@ -34,4 +34,4 @@ class RunnerExecutionError(AgentRunnerError):
def __init__(self, runner_id: str, message: str, retryable: bool = False):
self.runner_id = runner_id
self.retryable = retryable
super().__init__(f'Agent runner {runner_id} execution failed: {message}')
super().__init__(f'Agent runner {runner_id} execution failed: {message}')

View File

@@ -73,11 +73,11 @@ class AgentEventEnvelope(pydantic.BaseModel):
class BindingScope(pydantic.BaseModel):
"""Scope for agent binding."""
scope_type: typing.Literal["bot", "pipeline", "workspace", "global"] = "pipeline"
scope_type: typing.Literal["agent", "bot", "workspace", "global"] = "agent"
"""Scope type."""
scope_id: str | None = None
"""Scope identifier (bot_uuid, pipeline_uuid, etc.)."""
"""Scope identifier (agent_id, bot_uuid, etc.)."""
class ResourcePolicy(pydantic.BaseModel):
@@ -153,7 +153,7 @@ class AgentBinding(pydantic.BaseModel):
"""Runner ID to invoke."""
runner_config: dict[str, typing.Any] = pydantic.Field(default_factory=dict)
"""Runner binding configuration."""
"""Current Agent/runner configuration."""
resource_policy: ResourcePolicy = pydantic.Field(default_factory=ResourcePolicy)
"""Resource policy."""
@@ -167,6 +167,5 @@ class AgentBinding(pydantic.BaseModel):
enabled: bool = True
"""Whether binding is enabled."""
# Fields for Pipeline adapter
pipeline_uuid: str | None = None
"""Pipeline UUID (for Pipeline adapter)."""
agent_id: str | None = None
"""Host-side Agent/config identifier for this binding."""

View File

@@ -93,9 +93,9 @@ class AgentRunOrchestrator:
Args:
event: Event envelope from event gateway
binding: Agent binding configuration
binding: Agent binding
bound_plugins: Optional list of bound plugin identities for authorization
adapter_context: Optional adapter context from Pipeline adapter
adapter_context: Optional context from an entry adapter
Yields:
Message or MessageChunk for pipeline response
@@ -125,12 +125,12 @@ class AgentRunOrchestrator:
resources=resources,
)
# Merge adapter context if provided (for Pipeline adapter)
# Merge adapter context if provided
if adapter_context:
# Merge params into adapter.extra
if 'params' in adapter_context:
context['adapter']['extra']['params'] = adapter_context['params']
# Merge prompt into adapter.extra for Pipeline adapter consumers.
# Merge prompt into adapter.extra for transitional adapter consumers.
if 'prompt' in adapter_context:
context['adapter']['extra']['prompt'] = adapter_context['prompt']
# Set query_id if provided
@@ -420,7 +420,7 @@ class AgentRunOrchestrator:
Args:
result_dict: Raw result dict with type='state.updated'
event: Event envelope
binding: Agent binding configuration
binding: Agent binding
descriptor: Runner descriptor
"""
data = result_dict.get('data', {})

View File

@@ -114,12 +114,11 @@ class PipelineAdapter:
pipeline_config = query.pipeline_config or {}
ai_config = pipeline_config.get('ai', {})
runner_config = ai_config.get('runner_config', {}).get(runner_id, {})
pipeline_uuid = getattr(query, 'pipeline_uuid', None)
agent_id = getattr(query, 'pipeline_uuid', None)
# Build scope
scope = BindingScope(
scope_type="pipeline",
scope_id=pipeline_uuid,
scope_type="agent",
scope_id=agent_id,
)
# Build resource policy from pipeline config
@@ -142,7 +141,7 @@ class PipelineAdapter:
)
return AgentBinding(
binding_id=f"pipeline_{pipeline_uuid or 'default'}_{runner_id}",
binding_id=f"agent_{agent_id or 'default'}_{runner_id}",
scope=scope,
event_types=[runner_events.MESSAGE_RECEIVED],
runner_id=runner_id,
@@ -151,7 +150,7 @@ class PipelineAdapter:
state_policy=state_policy,
delivery_policy=delivery_policy,
enabled=True,
pipeline_uuid=pipeline_uuid,
agent_id=agent_id,
)
@classmethod
@@ -335,9 +334,6 @@ class PipelineAdapter:
# Handle bot_uuid
bot_uuid = getattr(query, 'bot_uuid', None)
# Handle pipeline_uuid
pipeline_uuid = getattr(query, 'pipeline_uuid', None)
return ConversationContext(
conversation_id=str(conversation_id) if conversation_id is not None else None,
thread_id=None,
@@ -347,7 +343,6 @@ class PipelineAdapter:
bot_id=bot_uuid,
workspace_id=None,
session_id=session_id,
pipeline_uuid=pipeline_uuid,
)
@classmethod
@@ -398,7 +393,6 @@ class PipelineAdapter:
"launcher_id": getattr(query, 'launcher_id', None),
"sender_id": str(getattr(query, 'sender_id', '')) if getattr(query, 'sender_id', None) else None,
"bot_uuid": getattr(query, 'bot_uuid', None),
"pipeline_uuid": getattr(query, 'pipeline_uuid', None),
},
)

View File

@@ -23,7 +23,7 @@ class AgentResourceBuilder:
- Apply 3-layer permission filtering:
1. Runner manifest declared permissions
2. Pipeline extensions_preference (bound plugins/MCP servers)
3. Runner binding config selected resources
3. Agent/runner config selected resources
- Build models list from authorized models
- Build tools list from bound plugins/MCP servers
- Build knowledge_bases list from config
@@ -68,7 +68,7 @@ class AgentResourceBuilder:
# Layer 2: Binding resource policy
resource_policy = binding.resource_policy
# Layer 3: Runner binding config
# Layer 3: Agent/runner config
runner_config = binding.runner_config
# Build each resource category
@@ -112,7 +112,7 @@ class AgentResourceBuilder:
# Get additional model UUID grants from resource policy.
allowed_uuids = resource_policy.allowed_model_uuids
# Add model resources from binding config schema
# Add model resources from Agent/runner config schema
await self._append_config_declared_model_resources(
models=models,
seen_model_ids=seen_model_ids,