Perfiles de outcomes para Agent v11¶
Estado: contrato de composición y evaluación, no decisión de retirada.
Agentes la superficie canónica para composición nueva.SymfonicAgentsigue siendo una API pública viva yagent/engine.pysigue atendiendo los turnos que no caben en el sobre migrado. Este catálogo no cambia defaults deFrameworkConfig, no abre ese sobre y no autoriza eliminar compatibilidad.
Un perfil es una receta explícita para obtener un outcome observable. No es una clase, preset oculto ni traductor de flags. La raíz de composición elige collaborators, grants y autoridad; las capabilities declaran las etapas que se ejecutan. Tener una capability construida, o un manifest con su nombre, prueba composición, no que el outcome haya ocurrido.
Reglas del catálogo¶
- Sólo hay cinco perfiles canónicos: chat sin estado, continuidad de memoria, herramientas enrutadas, gobernanza y continuación humana.
- La ausencia de una capability significa que ese comportamiento está apagado.
Agentno toma los booleanos deFrameworkConfigcomo perfil implícito. - La evidencia combina
composition_manifest, eventos/etapas y un efecto final determinista. Nunca se acepta sólo el texto de la respuesta. - Una raíz puede combinar perfiles si declara sus fronteras. Memoria + prompting renderiza recall; memoria sola recupera y publica, pero no pone recall ante el modelo.
- Una relación legacy es candidata de transición, no aprobación CORE-1. Cada fila que cambie o se elimine conserva decisión, nodo y evidencia propios.
Qué atestigua el manifest¶
Agent.composition_manifest es una atestación sin payload de la compilación:
capabilities, descriptores de etapa, herramientas contribuidas, preconditions y
un digest. Sirve para impedir que un eval describa un Agent distinto al que
se ejecutó. No contiene instrucciones, registros de memoria, prompts,
credenciales, texto de usuario ni prueba de una llamada externa.
Todo eval de perfil debe comprobar primero el digest/filas relevantes y después observar la etapa o puerto que hace material el outcome. Si se cambia la capability o sus collaborators, digest y batería de outcomes cambian juntos.
1. Chat sin estado¶
Outcome. Un proveedor recibe una vuelta con instrucciones, input y
herramientas estáticas declaradas; la llamada devuelve AgentResult o una
secuencia de AgentEvent. La continuidad entre vueltas pertenece al adopter,
que vuelve a pasar result.messages como history.
from symfonic import Agent
agent = Agent(provider, instructions="Ayuda con precisión.", tools=TOOLS)
result = await agent.run("Resume el pedido")
next_result = await agent.run("¿Qué falta?", history=result.messages)
| Aspecto | Contrato |
|---|---|
| Raíz pública | Agent(provider, instructions=..., model=..., tools=..., max_model_rounds=...) |
| Capabilities | Ninguna. Las herramientas estáticas pertenecen a tools=. |
| Evidencia | Manifest sin etapas/capabilities no solicitadas; llamada de proveedor; run devuelve resultado o stream entrega los eventos terminales esperados. |
| Autoridad | El adopter elige proveedor, instrucciones, modelo, herramientas y límite de rondas. El kernel concede model_call y tool_call sólo si hay herramientas. |
| No es | Sesión durable, recuperación de proceso, HMS, routing ni gobernanza. |
El baseline es deliberadamente pequeño. session_id en Agent.run es
correlación de vuelta, no un checkpointer ni historial persistido.
2. Continuidad de memoria¶
Outcome. Para un scope fijado por la raíz, un turno puede recuperar memoria, publicar la nueva interacción y hacer visible una publicación en una vuelta posterior. Con prompting apropiado, el recall entra además al prompt. Consolidación, extracción, ventana, activación y telemetría son extensiones explícitas, no defaults del perfil.
from symfonic import Agent
from symfonic.capabilities.memory import MemoryScope, memory_capabilities
from symfonic.capabilities.prompting import PromptingCapability
scope = MemoryScope("acme")
agent = Agent(
provider,
capabilities=[
*memory_capabilities(store, scope, extractor=extractor),
PromptingCapability(sources=[memory_prompt_source]),
],
)
memory_prompt_source representa la fuente que consume el snapshot de
retrieval; no es intercambiable con una cadena legacy. La raíz puede omitirla,
pero entonces sólo evalúa recall/publicación, no que el modelo vio memoria.
| Aspecto | Contrato |
|---|---|
| Raíz pública | memory_capabilities(store, scope, ...) junto a Agent(..., capabilities=...); para prompt, PromptingCapability compatible. |
| Capabilities/grants | La factory entrega MemoryCapability y GrantEffects("memory-read", "memory-write", "memory-flush"); añade memory-consolidate sólo con coordinator. |
| Evidencia | Manifest con retrieval, write y lifecycle; una vuelta escribe y flushes; la siguiente recupera en el mismo scope; otro scope no recupera. Si se promete prompt, capturar la solicitud del proveedor y el bloque de recall. |
| Autoridad | La raíz fija store, scope, límite, retrieval policy, extractor, consolidación y fuentes de prompt. La capability no puede otorgarse efectos. |
| No es | Traducción de auto_hydrate/auto_consolidate, ni transcript literal/restart. |
Un control anti-vacuidad cambia dato o scope y observa el puerto/etapa. Por
ejemplo, recent_turns se prueba en la llamada a WorkingWindow, no con texto
del modelo.
3. Herramientas enrutadas¶
Outcome. Una vuelta ofrece al proveedor sólo la paleta seleccionada por un router/pipeline explícito y después puede ejecutar una herramienta ofrecida. Routing reduce la oferta; no es por sí mismo una frontera de autorización.
from symfonic import Agent
from symfonic.capabilities.tools import ToolsCapability, keyword_router, tool_name
from symfonic.platform import GrantEffects
names = tuple(tool_name(tool) for tool in TOOLS)
agent = Agent(
provider,
tools=TOOLS,
capabilities=[
GrantEffects("memory-read"),
ToolsCapability(
registered=names,
entries_for=keyword_router(KEYWORDS, registered=names),
),
],
)
| Aspecto | Contrato |
|---|---|
| Raíz pública | Agent(tools=TOOLS, capabilities=[GrantEffects(...), ToolsCapability(...)]) |
| Capabilities/grants | ToolsCapability declara tools.routing; los grants dependen del router/stages. La raíz declara exactamente los efectos necesarios. |
| Evidencia | Manifest con tools.routing y herramientas registradas; dos cues dan paletas distintas antes de bind_tools; una herramienta permitida ejecuta y deja su efecto esperado. Probar run y stream cuando el host lo publique. |
| Autoridad | La raíz registra herramientas servibles, selecciona router/pipeline/preconditions y grants. Governance/preconditions autorizan, reparan o rehúsan llamadas. |
| No es | intent_filter_mode, garantía de que el modelo llamará una herramienta ni autorización de una herramienta no ofrecida. |
La mutación de cue o retirada del routing debe volver rojo el spy de
bind_tools; sólo comprobar que existe ToolsCapability sería vacuo.
4. Gobernanza¶
Outcome. Las reglas compuestas pueden enmendar o rechazar una acción/draft antes de que llegue al consumidor. Una negativa debe atribuir su regla y no producir el efecto prohibido; una enmienda debe observarse en la entrada del puerto posterior, no sólo en un registro.
from symfonic import Agent
from symfonic.platform import governance
agent = Agent(
provider,
tools=TOOLS,
capabilities=[governance(preconditions=[policy], decisions=decision_log)],
)
| Aspecto | Contrato |
|---|---|
| Raíz pública | Agent(..., capabilities=[governance(...)]), con los collaborators de policy, reflector, decision sink y reglas autorizados. |
| Capabilities/grants | governance(...) compone etapas de ingreso/egreso y, donde aplique, preconditions de tool call. |
| Evidencia | Manifest con etapas/preconditions; caso rechazado atribuye regla y no llama al tool/event sink prohibido; caso enmendado observa el dato enmendado en el siguiente puerto. Drenar stream si se ofrece. |
| Autoridad | El despliegue define reglas, patrones, decision sink y efectos. Governance puede negar/enmendar; no recibe autoridad implícita por existir. |
| No es | Default global de seguridad, equivalencia textual con booleans legacy ni prueba de que toda respuesta histórica fue reescrita. |
Una caída de reflector conserva su política fail-open vigente donde aplique;
no debe relabelarse como rechazo. Una negativa válida prueba ausencia del side
effect, no solamente GovernanceRefused.
5. Continuación humana¶
Outcome. El agente puede ofrecer una interacción humana que pausa una
vuelta; un AgentHost recupera después un token duradero, deriva scope desde
claims autenticados y continúa una sola vez. Capability y host son dos mitades
obligatorias.
from symfonic import Agent
from symfonic.capabilities.human import human_interaction
from symfonic.platform import AgentHost, human_continuation
interaction = human_interaction(
signer=signer,
binding=binding_for_current_turn,
encode_token=encode_token,
decode_token=decode_token,
consumption=shared_consumption,
)
host = AgentHost(
composer=lambda scope, resources: Agent(
resources.provider, capabilities=[interaction],
),
resources=resources,
continuation_factory=human_continuation(
capability=interaction,
scope_for_claims=scope_for_verified_claims,
),
)
En una raíz real, el capability entregado al Agent y a
human_continuation es el mismo objeto de token/ledger/checkpoint. La función
binding debe producir el binding del turno y scope que la raíz ya verificó.
Sin decode_token se puede pausar pero no hay lector público de continuidad;
no satisface el perfil.
| Aspecto | Contrato |
|---|---|
| Raíz pública | human_interaction(...) dentro de Agent, más AgentHost(..., continuation_factory=human_continuation(...)) |
| Capabilities/grants | HumanInteractionCapability ofrece interacción y guarda pausa; AgentHost posee agentes por scope y el redemption service. |
| Evidencia | Manifest con herramienta/etapa humana; proceso 1 pausa; proceso 2 crea host nuevo y reanuda. Probar scope mismatch, payload corrupto, expiry y segundo canje; sólo el válido continúa. |
| Autoridad | Raíz provee signer, binding, codec, TTL, ledger/consumption, checkpoint y scope_for_claims. El host, no HTTP ni el agente, deriva scope. |
| No es | Agent.resume(token), importación SQLite legacy, ni paridad de streaming token a token con el motor legado. El puerto HTTP tipado entrega el resultado o los eventos que exponga la raíz. |
El consumo en memoria sólo es válido para un proceso. Con réplicas, el despliegue elige y prueba un consumption store compartido.
Relación con filas legacy¶
Esta tabla es un índice de transición, no un veredicto de producto. “Equivale”
sólo repite equivalent-proven de la matriz existente; no aprueba sustituir un
consumidor. “Cambia” y “elimina” requieren CORE-1 por fila antes de migrar una
raíz o modificar compatibilidad.
| Perfil | Filas legacy relacionadas | Relación actual | Límite |
|---|---|---|---|
| Chat sin estado | state_class, messages_cache_policy, activation_log_mode |
cambia / elimina | State es mapping por vuelta; no hay conversión de clase, rolling cache ni footer equivalente. |
| Memoria | working_memory_recent_turns, enabled_layers, hydration_min_relevance, scope_blend_mode, quick_nap_interval, scorer_on_hot_path |
cambia | Son policy/collaborators explícitos; cada uno conserva semántica y evidencia de fila. |
| Herramientas enrutadas | procedural_force_first_action_tool, skill_auto_approve, read_only_tools |
equivale / cambia | Forced choice tiene evidencia nativa; auto-approval sigue inactivo y read-only es governance explícita. |
| Gobernanza | metacognition_*, credential_patterns, fabrication_refuse_min_confidence, domain.core_preferences |
cambia | Policies y pruebas nativas no aprueban firmas/defaults ni activación de preferencias. |
| Continuación humana | dev_sqlite_checkpoint_path, ask_user_pause_ttl_seconds, ask_user_tool_descriptions |
cambia / equivale | TTL/descripción tienen evidencia pública; token, scope y durability son composición explícita, sin import de checkpoint legacy. |
Prompt, extraction, cache, subagents, callbacks y transporte quedan fuera hasta que tengan outcome y raíz nativos propios. No se absorben por similitud de nombre.
Batería común de certificación¶
Para cada perfil anunciado por una raíz:
- Construir
Agentdirectamente, sinFrameworkConfig,SymfonicAgentniengine.py. - Afirmar manifest/digest y las etapas, tools o preconditions relevantes sin inspeccionar payloads.
- Ejecutar fixture determinista que observe etapa y efecto final; usar
runy añadir stream cuando el root prometa streaming. - Ejecutar control negativo: retirar capability/grant o cambiar input/scope debe invalidar el outcome por la razón declarada.
- Para una fila legacy, añadir diferencial por fila y decisión de owner. Un perfil verde no convierte una fila a equivalente ni habilita retirar fallback.
Las pruebas existentes que cubren parte de esta base son
tests/retirement/test_core15_measurable_native_evidence.py (memoria/prompt),
tests/agent/cutover/test_lazy_palette_end_to_end.py (paleta routed),
tests/platform/test_governance_amends.py y
tests/platform/test_governance_refusal_precedence.py (autoridad), y
tests/platform/test_fp3_public_preservation_journeys.py (continuación tras
reinicio). Son evidencia localizada, no certificación automática de todas las
raíces consumidoras.
Límite de migración¶
Una root adopta un perfil con collaborators públicos, protocolos de transporte
ya probados y telemetría de fallback separada del tráfico legacy elegido por
configuración. Cero fallbacks requiere el evento durable CORE-24; el manifest
de Agent no mide producción.
La secuencia es: definir outcome, componer perfil, certificarlo en una raíz delimitada, decidir cada fila legacy afectada y sólo entonces migrar consumidores. Ninguna etapa implica que el engine dejó de servir turns ni que el retirement gate quedó satisfecho.