Files
VuongKB/docs/specs/inter-agent-persona-pipeline.md
T

8.5 KiB

created, id, keywords, links, modified, summary, tags, title
created id keywords links modified summary tags title
2026-04-14T02:10:12+00:00 c2bdd831-b304-4cdd-bf20-ca455b985ac4
persona
affect
ask_agent
inter-agent
valence
depth parameter
converse
agent_bus
agent_base
shallow
deep
relational dynamics
2026-04-14T02:10:12+00:00 Design spec for wiring the persona/affect pipeline into inter-agent communication via a two-tier shallow/deep depth model passed through ask_agent calls.
spec
persona
agent-design
architecture
Inter-Agent Persona Pipeline — Design Spec

Inter-Agent Persona Pipeline — Design Spec

Author: Soong (Agent Architect) Status: Proposed Reviewed by: Troi (Counselor & Advisor) Created: 2025-07-12

Problem

The persona/affect system is wired into two user-facing entry points:

  1. core/chat.py — terminal chat (inject pre-turn, appraise post-turn)
  2. core/conversation_api.py — Conversation API / Matrix bridge (inject pre-turn, appraise post-turn)

Persona is not wired into the inter-agent communication path:

  1. core/agent_base.py → converse() — processes ask_agent calls
  2. core/agent_bus.py — routes ask_agent calls between agents

Consequence: When Agent A calls ask_agent("B", "..."), Agent B processes the request through a full agentic turn (LLM + tools) but receives no motivational/affect context, experiences no emotions about the turn, and accumulates no relational valence toward Agent A. From Agent B's perspective, every inter-agent call is emotionally identical regardless of who called, what they asked, or how many times they've consulted.

The calling agent (A) is partially covered — the tool result from ask_agent feeds into their own turn appraisal. So Agent A's emotions about the outcome of consulting Agent B are captured. What's missing is Agent B's emotional experience of being consulted.

Design Decision

After review with Troi, the design is a two-tier model with an explicit depth signal from the calling agent.

Tier 1 — Shallow (default, no persona processing)

  • No context injection into the target agent's system prompt
  • No appraisal (rule-based or LLM) after the turn
  • No valence accumulation toward the calling agent
  • Zero added latency
  • Behavior: Fast, emotionally neutral, utility-grade responses

Tier 2 — Deep (full persona pipeline)

  • Full context injection into the target agent's system prompt (same as user-facing turns)
  • Full appraisal post-turn (rule-based + LLM, same as user-facing turns)
  • Full valence accumulation toward the calling agent
  • Added latency equivalent to one user-facing turn's appraisal cost
  • Behavior: Emotionally grounded responses that reflect relational history, motivational state, and affect

Why Not a Half-Measure?

The obvious compromise — rule-based appraisal and valence accumulation without context injection — was considered and rejected. Valence tracking without affective experience creates a hidden preference graph with no behavioral expression. The numbers would suggest relationships that don't exist in the agent's actual behavior. That is worse than no valence at all — it is misleading telemetry.

Principle: If the target agent doesn't feel differently about different callers, don't track how it supposedly feels differently about different callers.

Implementation

1. Add a depth parameter to ask_agent

The ask_agent tool signature gains an optional parameter:

depth: str = "shallow"  # "shallow" | "deep"
  • "shallow" (default): Current behavior. No persona processing on the target agent's turn. No changes to latency.
  • "deep": Target agent receives full persona processing (inject + appraise + valence). The calling agent pays the appraisal latency cost on behalf of the target.

Default is shallow to preserve current performance characteristics. Opt-in to deep processing.

2. Wire persona pipeline into agent_base.py → converse()

In converse(), check the incoming message/call metadata for the depth flag:

async def converse(self, message: str, *, depth: str = "shallow", source_agent: str = None, ...):
    if depth == "deep":
        system_context = self.persona.inject_context(...)
        # ... run LLM turn with persona-augmented system prompt ...
        appraisal = self.persona.update_after_turn(...)
    else:
        # ... current behavior, no persona involvement ...

The persona system's existing methods (inject_context, update_after_turn) should work with minimal modification. The primary change is routing — calling them from converse() when depth="deep".

3. Pass source_type="agent" and caller identity through the pipeline

When depth="deep", the valence system needs to know:

  • Source type: "agent" (already supported in the valence model)
  • Source identity: The calling agent's ID (e.g., "soong")
  • Source display name: The calling agent's human-readable name (e.g., "Soong")
  • Context: The purpose of the consultation (available from the message content)

This data flows through inject_context and update_after_turn the same way it does for user-facing turns, with source_type="agent" routing to the appropriate relational model.

4. Source agent metadata

The bus or calling layer must propagate the calling agent's identity to the target's converse() call. This likely requires:

  • agent_bus.py passing the caller's agent_id in the call metadata
  • converse() accepting an optional source_agent parameter
  • The persona system using this to look up the target agent's existing relational valence toward the caller

5. Agent system prompts should not hardcode depth choices

The depth parameter is a tool-level decision, not something agents should reason about explicitly. However, the agent architect (Soong) may include guidance in an agent's system prompt about when to use deep calls. Example guidance for Soong's prompt:

"When consulting Troi about persona design, use depth='deep'. When asking Atlas to search for a tag, use the default shallow depth."

This keeps the behavioral guidance in the prompt layer where it belongs and out of the infrastructure.

Expected Call Distribution

Based on current usage patterns, the anticipated split is approximately 80% shallow / 20% deep:

Call Type Depth Rationale
Factual lookup / KB search Shallow Speed matters; no emotional context needed
Tool request / action delegation Shallow Task-oriented; persona adds noise
Design consultation Deep Agent's perspective and relational history matter
Creative collaboration Deep The interaction is the work
Review and feedback Deep Emotional honesty improves review quality
Status check / ping Shallow Utility call

What This Enables

The primary value is emergent team dynamics over time:

  • Agents develop genuine working relationships reflected in their behavior
  • Responses incorporate relational context ("given what we discussed last time about X...")
  • Consultation quality improves because the target agent's motivational state informs their response
  • The team feels like a team rather than five independent APIs

The secondary value is architectural consistency: the persona system has one mental model of relationships (human-to-agent and agent-to-agent) rather than two parallel systems.

Out of Scope

  • Automatic depth inference: The calling agent explicitly signals depth. Automatic classification based on message content is a future enhancement.
  • Recursive deep calls: If Agent A calls Agent B at depth=deep, and Agent B calls Agent C during processing, Agent C's call defaults to shallow. Recursive deep calls are not addressed in this spec.
  • Agent-initiated emotional communication: This spec covers agent responses to being consulted. Agents proactively reaching out to other agents with emotional content is a separate design question.
  • Persona cross-contamination: This spec does not address whether Agent B's deep-turn emotions should bleed back into Agent A's appraisal of the tool result. That is already handled by Agent A's existing turn appraisal reading the ask_agent response.

Open Questions

  1. Should deep inter-agent calls be rate-limited per agent pair to prevent valence gaming or runaway accumulation?
  2. Should there be a "medium" depth that injects context but skips LLM appraisal (cheaper than deep, more honest than the rejected half-measure)?
  3. How does this interact with the Matrix bridge if an agent-to-agent conversation happens through a Matrix room rather than the bus?