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
81%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
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.
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.