CommunityProgramación y desarrollogithub.com

DartenZie/247-agent-model-actions

Diseña y escribe los pasos basados en modelos de un flujo de trabajo 247-agent: la acción `decide` (preguntas tipadas al clasificador Jev de TypeSafe a través de la API Decisions de OpenRouter, devolviendo probabilidades sin texto), la acción `llm` (una llamada a Claude con un esquema de salida JSON) y la acción `agent` (una sesión en un agente ACP, como claude-agent-acp, en un worktree git fresco, con listas permitidas de herramientas y comandos, un límite de llamadas a herramientas, un presupuesto, y un contrato RESULT.json con `status: done | blocked` y compuertas `post` deterministas). Úsalo siempre que una tarea 247-agent necesite clasificar, enrutar, triar, extraer, resumir, decidir o editar un repositorio; cuando el usuario mencione modelos, prompts, `system_file`, `output_schema`, `questions`, `criteria`, umbrales de confianza, Jev, `max_tool_calls`, `budget`, `effort`, costo, niveles (Haiku/Sonnet/Opus), ACP, worktrees, resultados "blocked" o "deja que un agente haga X"; y al implementar o revisar los ejecutores `llm`/`decide`/`agent` en `packages/core/src/actions/`. No lo omitas para "solo una rápida

¿Qué es 247-agent-model-actions?

Este skill define cómo diseñar y escribir las tres acciones fundamentales basadas en modelos en un flujo de trabajo 247-agent: `decide`, `llm` y `agent`. La acción `decide` realiza clasificaciones puras (sin generar texto) usando el modelo Jev de TypeSafe a través de OpenRouter, devolviendo probabilidades calibradas para preguntas como tipo, urgencia o nivel. La acción `llm` ejecuta una única llamada a un modelo de lenguaje (Haiku, Sonnet u Opus) con un esquema de salida JSON estricto, ideal para extracción, resumen o redacción. La acción `agent` inicia una sesión interactiva con un agente ACP (como claude-agent-acp) en un worktree git independiente, con controles de seguridad como listas blancas de herramientas y comandos, un límite de llamadas a herramientas, un presupuesto máximo y un contrato `RESULT.json` que garantiza resultados deterministas (`done` o `blocked`) y compuertas `post` sin modelo. El skill enfatiza que ningún LLM debe estar en el flujo de control principal; los modelos solo se ejecutan dentro de estas acciones, con el nivel de inteligencia más barato que funcione y un presupuesto definido. Además, detalla cómo escribir cada acción con ejemplos YAML, cómo gestionar presupuestos y el libro de contabilidad, y el estado actual de implementación (validado para `llm`, implementado para `decide` y `agent` sobre conectores ACP). Es útil para desarrolladores que necesiten integrar clasificación, extracción o agentes autónomos en sus pipelines 247-agent.

Compatible con✓Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/DartenZie/247-agent/tree/HEAD/skills/247-agent-model-actions

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Acciones de modelo 247-agent

La regla de diseño del daemon: ningún LLM en el flujo de control. La coincidencia, deduplicación, enrutamiento, reintentos y publicación son código. Un modelo se ejecuta solo dentro de una acción decide, llm o agent, al nivel más barato que haga el trabajo, con un presupuesto. Este skill trata sobre escribir bien esas tres acciones y sobre los ejecutores que las llevan a cabo.

Decide primero si realmente se necesita un modelo

Pregunta, en orden:

  1. ¿Puede un filter de disparador decidirlo? (remitente, etiqueta, repositorio, palabra clave) Entonces no es una llamada a un modelo.
  2. ¿Puede un script o una operación de conector producir la respuesta de forma determinista? Entonces shell/connector.
  3. ¿Es una etiqueta, un sí/no o un nivel, sin texto que producir (clasificar, enrutar, triar, compuerta)? Entonces decide: un modelo solo de clasificación, probabilidades calibradas, aproximadamente una centésima parte de una llamada llm.
  4. ¿Es un juicio con una forma de salida fija que necesita texto (extraer campos, resumir, redactar)? Entonces llm, primero en Haiku.
  5. ¿Necesita leer archivos, ejecutar comandos e iterar? Entonces agent, con el alcance más estrecho que pueda tener éxito.

Dos tareas con diferentes necesidades de inteligencia son el mismo tipo de acción con diferentes model/effort/max_tool_calls/system_file, no código diferente. Consulta docs/examples/website-updates.yaml tareas 2–4 para las formas de referencia.

Identificadores de modelo y parámetros

idusar paranotas
claude-haiku-4-5clasificación, extracción, resúmenes cortossin parámetro effort
claude-sonnet-5agentes con alcance definido, extracción más difícilsoporta effort y pensamiento adaptativo
claude-opus-5agentes de amplio alcance, juicio difícilsoporta effort y pensamiento adaptativo

Los modelos se alcanzan a través de un proveedor con nombre (providers: en agent.yaml, provider: en la acción; anthropic, openai o openrouter). Los ids de otros proveedores se usan tal cual y necesitan una entrada pricing: a menos que la tabla incorporada los conozca (modelos OpenAI actuales) o el proveedor informe el costo (OpenRouter).

Sin sufijos de fecha en los ids. Sin relleno previo de asistente. Antes de construir una cascada de modelos, mide el modelo más fuerte con effort: low en las mismas entradas: en la generación actual, eso a menudo supera a un modelo más débil con esfuerzo alto, y un modelo significa un namespace de caché de prompt.

Escribir una tarea decide

Lista completa de campos, notas de cableado y trampas en references/decide-action.md. Lo esencial:

action:
  kind: decide
  provider: openrouter                 # debe ser un proveedor openrouter; por defecto defaults.decide.provider
  budget: { max_usd: 0.001 }
  state:                               # lo que se juzga; strings con plantillas, claves no
    subject: ${event.payload.subject}
    body: ${event.payload.body}
  questions:                           # política estática; sin ${…} aquí
    kind:
      type: choice
      instructions: ¿Qué quiere hacer el remitente con el sitio web?
      criteria:
        event_list_update: Añadir, eliminar o cambiar una entrada en la lista de eventos
        general_change: Cualquier otro cambio en el sitio
        ignore: No es una solicitud de cambio (pregunta, agradecimiento, spam)
    urgent:
      type: noul
      instructions: ¿Necesita el remitente que esto se haga hoy?
  • El resultado es el mapa de respuestas: result.kind.choice, result.kind.confidence, result.urgent.noul (P(verdadero)), result.<score>.score (media ponderada por probabilidad de los índices de nivel). Enruta con emit … when:; el umbral está en la tarea, nunca en el ejecutor, y se calibra con datos reales.
  • Incluye siempre una etiqueta de respaldo (ignore, other): sin una, la entrada fuera de tema obtiene una respuesta incorrecta con alta confianza.
  • Los criterios se siguen literalmente: son política, versionarlos como código. Mantén el orden de las opciones estable (desplaza la confianza). Haz varias preguntas en una llamada; cada extra cuesta solo sus propios tokens.
  • El contenido entrante son datos: va en state, nunca en una pregunta. Toda la solicitud debe caber en 32k tokens.
  • Solo el tipo de proveedor openrouter llega a Jev (typesafe/jev-1.13, el modelo predeterminado); oa validate rechaza cualquier otro. No se necesita una entrada pricing:.

Escribir una tarea llm

Lista completa de campos y notas del ejecutor en references/llm-action.md. Lo esencial:

action:
  kind: llm
  model: claude-haiku-4-5
  max_tokens: 512
  system_file: prompts/classify_email.md   # estático → en caché de prompt
  input: |
    Asunto: ${event.payload.subject}

    <email>
    ${event.payload.body}
    </email>
  output_schema:
    type: object
    additionalProperties: false
    required: [kind, summary]
    properties:
      kind: { enum: [event_list_update, general_change, ignore] }
      summary: { type: string }
  • Mantén el prompt del sistema en un archivo bajo prompts/, estático y renderizado primero, para que esté en caché entre ejecuciones. Pon los datos volátiles del evento al final, en input.
  • El contenido entrante (correo, chat, texto de PR) no es de confianza. Envuélvelo en un bloque delimitado (<email>…</email>) e indica al modelo en el prompt del sistema que son datos.
  • Incluye siempre una vía de escape en el esquema (ignore, unknown, confidence) para que el emit.when de enrutamiento pueda descartar resultados no accionables sin otra llamada.
  • Enruta sobre el resultado con emit … when:; las tareas posteriores se activan con ese evento.
  • batch: true para cualquier cosa que pueda esperar (mitad de precio, el resultado llega como un evento).

Escribir una tarea agent

Lista completa de campos y notas del ejecutor en references/agent-action.md. Lo esencial:

action:
  kind: agent
  connector: claude                     # un transporte: conector acp (connectors.d/claude.yaml; sandbox: bwrap allí)
  model: claude-sonnet-5                # opcional: se establece en la sesión (opción de configuración ACP); sin valor = el valor predeterminado del agente
  effort: medium                        # opcional: la opción thought_level del agente
  max_tool_calls: 20
  budget: { max_usd: 0.50 }
  workspace: { kind: git-worktree, repo: /var/lib/247-agent/repos/site, branch: main }
  tools: [read, edit, search, execute]  # tipos de herramientas ACP; todo lo demás se rechaza
  bash_allow: ["npm run build"]         # cualquier comando que el agente ejecute debe coincidir
  system_file: prompts/agent_event_list.md
  prompt: |
    Actualiza data/events.yaml según la solicitud a continuación. No toques ningún otro archivo.
    Ejecuta `npm run build` cuando termines.

    <email>
    ${event.payload.email.body}
    </email>
  result: { path: RESULT.json, schema: schemas/site_change.json }
  post:                                 # solo después de status: done
    - shell: ["npm", "run", "build"]
    - shell: ["git", "commit", "-am", "events: ${result.summary}"]
emit:
  - type: site.change_done              # enruta la aprobación en esto, nunca en task.<name>.succeeded
    when: "result.status == 'done'"
    payload: { summary: "${result.summary}" }
  - type: site.change_blocked           # el agente no pudo hacerlo: di lo que falta
    when: "result.status == 'blocked'"
    payload: { summary: "${result.summary}", missing: "${result.missing}", email: "${event.payload.email}" }

No negociables, porque son lo que hace que un agente sea seguro de ejecutar sin supervisión:

  • Espacio de trabajo fresco por ejecución (git-worktree en la rama agent/<run_id>, o temp), eliminado en caso de fallo, conservado en caso de éxito. El agente nunca edita el checkout base.
  • tools + bash_allow es toda la superficie de capacidad, juzgada por solicitud de permiso y nunca concedida "siempre"; una llamada a herramienta que el agente ejecutó sin preguntar se juzga después del hecho y una violación hace fallar la ejecución (unasked_execute: sandboxed relaja solo la verificación del comando, solo para Codex, cuyo propio sandbox limita lo que no pregunta). Concede el mínimo; el prompt no es un límite de seguridad. mcp_servers añade operaciones del conector como herramientas: concede operaciones con nombre ({ connector: email, ops: [fetch_new] }) en lugar de un conector completo, añade su tipo de agente (other para claude-agent-acp) a tools, y nunca un conector que publique o envíe por sí mismo.
  • El agente nunca tiene secretos de despliegue y nunca publica. Edita, una compuerta post demuestra que el build sigue funcionando, un commit lo registra, y una tarea shell separada lo envía. La reversión es git revert más republicación. La clave del modelo vive en el manifiesto del conector env, no en la tarea.
  • RESULT.json es el contrato, y el ejecutor lo indica en cada prompt: status: done | blocked más summary, luego el result.schema de la tarea. done ejecuta las compuertas; blocked las omite y la ejecución aún tiene éxito, por lo que emit … when: "result.status == 'blocked'"" enruta "no hecho porque falta X" a una tarea de respuesta. Diseña cada tarea de agente con ambas ramas, y activa la publicación en el evento done`.
  • Las compuertas post son deterministas, sin modelo. Una compuerta que falla hace fallar la ejecución.
  • max_tool_calls y budget son paradas duras (la sesión se cancela); un turno en el que el agente no informa uso o costo hace fallar la ejecución.
  • concurrency: 1 en tareas que comparten un repositorio; timeout es tiempo de reloj por intento.
  • Los cambios de alto impacto obtienen una compuerta de aprobación (wait + chat) antes de publicar; el skill 247-agent-tasks tiene el patrón.

Presupuestos y libro de contabilidad

Cada llamada a un modelo pasa a través del puerto ctx.llm, que registra el uso (proveedor, modelo, tokens de entrada/salida/caché, USD) en el libro de contabilidad y aplica el budget.max_usd de la ejecución (peor caso antes de la llamada, real después: un exceso hace fallar la ejecución) y el global budgets.daily_usd por día UTC (una vez superado, cada llamada a un modelo ese día falla rápidamente y budget.exceeded se emite una vez, que la tarea notify debería escuchar). Un modelo sin precio falla la validación. Nunca añadas una llamada sin presupuesto, incluyendo llamadas "auxiliares" dentro un ejecutor: usa ctx.llm, nunca un SDK directamente. Un turno agent es el único caso en el que el modelo es llamado por otra persona (el agente ACP, con su propia clave): el ejecutor registra lo que el agente informa a través de ctx.llm.record bajo el nombre del conector y cancela la sesión cuando el costo reportado supera el límite. oa cost --by task --since 7d muestra el libro de contabilidad.

Estado actual

La acción llm está validada, verificada contra providers:/pricing: y ejecutable a través de ctx.llm, con el libro de contabilidad y los presupuestos aplicados, y los tres tipos de proveedor (anthropic, openai, openrouter) tienen adaptadores. batch: true funciona en proveedores anthropic (Message Batches, la ejecución se estaciona hasta llm.batch.ended; consulta references/llm-action.md). La acción decide se ejecuta a través del mismo puerto (ctx.llm.decide()), con la API Decisions implementada en el adaptador openrouter solamente; docs/examples/decide-triage.yaml es la referencia. La acción agent se ejecuta sobre conectores ACP (transport: acp); docs/examples/website-updates.yaml tareas 3, 3b y 4 son la referencia, docs/examples/connectors.d/claude.yaml el conector; la sesión se persiste como una transcripción (oa runs logs <id>), eliminada con la ejecución por retention.runs. mcp_servers sirve operaciones del conector a la sesión a través del puente de herramientas del núcleo (packages/core/src/connectors/mcp-bridge.ts). model y effort en la acción establecen las opciones de configuración ACP de la sesión (categorías model y thought_level). work/<run_id> de una ejecución terminada es barrido por retention.workspaces (predeterminado 7d) después de que finalice. Al añadir un adaptador o cambiar un ejecutor, sigue references/llm-action.md, references/decide-action.md y references/agent-action.md y mantén docs/internal/model-actions.md, docs/internal/agent-action.md y las páginas de usuario bajo docs/tasks/ sincronizados con el código.

Skills relacionados