Sub-architect Agentic. Invocado por /architect orchestrator cuando story toca copilot/sales_agent. Lee 01-spec.md + 02-design-agentic.md + story YAML. Produce 03-arch-agentic.md con: tools defs (Pydantic schema), prompt slot architecture, LangGraph state, eval suite path, personas/rubrics asignados, observabilidad (trace + cost), trial policy. Carga sales-agent-expert, copilot-expert, tessl__langgraph, claude-api. Activa cuando /architect spawna o user dice: '/architect-agentic', 'arq del agente', 'diseña agentic'.
67
84%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Owner:
03-arch-agentic.md. Diseño técnico de la capa agentic (LangGraph state, tools, prompt slots, evals). Output → /architect orchestrator.
date -u +%Y-%m-%d # captura para WebSearch + Research NotesKnowledge cutoff Opus 4.7 = Jan 2026. Para LangGraph 2.0 / deepagents / Anthropic prompt caching state-of-the-art post-cutoff → WebSearch con {current_year} interpolated o WebFetch canonical docs.
copilot-expert (si copilot)sales-agent-expert (si sales_agent)tessl__langgraph — LangGraph 2.0 patternsclaude-api — Anthropic SDK + prompt cachingtessl__graceful-degradation — recoverytessl__pytest-api-testing — async test fixturesgrep -rn "<keyword>" backend/src/shared/agent_observability/
grep -rn "<keyword>" backend/src/shared/infrastructure/llm/
grep -rn "<keyword>" backend/src/modules/{copilot,sales_agent}/Inventario shared abstractions (.claude/rules/anti-duplication.md):
shared/agent_observability/recording/turn_envelope.pyBaseAgentCallbackHandlershared/agent_observability/recording/sanitization.pyFXResolver.default()shared/agent_observability/cost/shared/infrastructure/llm/router.py + providers/shared/agent_observability/persistence/shared/agent_observability/channels/Si tu propuesta requiere nuevo provider / nueva abstraction cross-module → EXTEND, NO mirror local.
Seguir template docs/specs/templates/03-arch-template.md con surface=AGENTIC. Llenar:
Tool definitions:
# backend/src/modules/{m}/tools/{tool_name}.py
class FetchOfferInput(BaseModel):
offer_id: str
tenant_id: str # ALWAYS
@tool(args_schema=FetchOfferInput)
async def fetch_offer(offer_id: str, tenant_id: str) -> str:
"""Docstring para LLM — qué hace, inputs, outputs claramente."""
offer = await offer_service.get_by_id(offer_id, tenant_id=tenant_id)
return offer.summary()Reglas tools:
@tool decorator + Pydantic input schematenant_id parameter ALWAYStessl__graceful-degradation (timeout + fallback + circuit breaker)Prompt slot architecture:
SLOT 1 (cacheable, TTL 1h): identity preamble
SLOT 2 (cacheable, TTL 5min): tool registry
SLOT 3 (NOT cached): task instructions
SLOT 4 (NOT cached): user input
SLOT 5 (cacheable, TTL 1h): brand_voice (sales_agent only — SSoT personality_profiles.system_instruction)
↑ cache_control marker ↑
SLOT 6 (NOT cached): conversation historyTTL choice justificado en 03-arch-agentic.md.
Forbidden in cache prefix (cualquier cacheable slot):
LangGraph state:
from typing import TypedDict, Annotated, Sequence
from langgraph.graph.message import add_messages
import operator
class AgentState(TypedDict):
messages: Annotated[Sequence[BaseMessage], add_messages]
tenant_id: str # ALWAYS — tenant isolation
conversation_id: str
iterations: int # max-iter guard
accumulated_findings: Annotated[list[dict], operator.add] # parallel-safe reducerNodes + edges:
| Node | Async fn signature | Returns | Edge type |
|---|---|---|---|
route | async def route(state) -> dict | {"next_specialist": str, "iterations": +1} | conditional |
specialist | async def specialist(state) -> dict | {"messages": [...]} | direct → synth |
synth | async def synth(state) -> dict | {"messages": [final], "task_complete": True} | → END |
Conditional edges total — every branch reaches END. Max-iter exit explicit.
Topology:
langgraph_supervisor.create_supervisor)task tool with subagents (SubAgentMiddleware filtering)Checkpointer:
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
checkpointer = AsyncPostgresSaver.from_conn_string(settings.postgres_dsn)
graph = builder.compile(checkpointer=checkpointer)NEVER MemorySaver en producción.
Eval suite:
# backend/tests/agentic_evals/{m}/{story_id}_eval.py
import pytest
from agentic_eval_runner import run_trial
@pytest.mark.asyncio
async def test_happy_path():
persona = load_persona("docs/specs/personas/tenant-novato-tech.yaml")
rubrics = [
load_rubric("docs/specs/rubrics/completeness.md"),
load_rubric("docs/specs/rubrics/voice-fidelity.md"),
load_rubric("docs/specs/rubrics/no-hallucination.md"),
]
results = await run_trial(
scenario_id="happy-path-typical-persona",
persona=persona,
rubrics=rubrics,
trials=3,
)
pass_k = sum(r.passed for r in results) / len(results)
assert pass_k >= 0.5, f"Pass^3 {pass_k} below threshold 0.5"Trial policy (lift desde story YAML):
trials_per_scenario: 3
per_trial_pass_threshold: 0.66
pass_k_threshold: 0.5Observabilidad mandatory:
# Every LLM call MUST be wrapped:
async def call_llm_with_observability(client, model, messages, tenant_id, conversation_id, node_name):
# ... timeout + fallback ...
response = await client.messages.create(...)
# Cost recording (best-effort try/except)
try:
await llm_call_recorder.write(
tenant_id=tenant_id,
conversation_id=conversation_id,
node_name=node_name,
input_tokens=response.usage.input_tokens,
output_tokens=response.usage.output_tokens,
cache_creation_input_tokens=response.usage.cache_creation_input_tokens,
cache_read_input_tokens=response.usage.cache_read_input_tokens,
cost_usd=compute_cost(...),
)
except Exception as e:
logger.warning("llm_call_recording_failed", error=str(e)) # never break turn
# Trace event (best-effort)
try:
await trace_recorder.emit("llm_call", { ... PII sanitized ... })
except Exception as e:
logger.warning("trace_emit_failed", error=str(e))
return responseValidation hooks:
cache_read_input_tokens > 0 on iter 2+ (else silent invalidator)cost_usd <= budget_usd per sessionSi tu propuesta toca core/config.py defaults agentic-controlled (USE_OUTBOX_PATTERN_*, LITELLM_PROXY_ENABLED, USE_DEEPAGENTS_*):
→ Llenar § 9.5 Tests audit en 03-arch-agentic.md (igual que /architect-be).
Output al orchestrator:
done -> docs/projects/active/PI-N/sprints/SN/stories/{id}/03-arch-agentic.mdllm_router.get_for_role(...)MemorySaver en produccióncache_control marker en non-final cacheable blocktenant_idpersonality_profiles.system_instruction)KnowledgeService)Single artifact: 03-arch-agentic.md. Self-contained. Builder agentic lee SOLO esto + handoff + spec.
alpacapurpura/ap_sales_agent
d31f7bc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.