✅ Meta App Review approved — GoSendAPI Cloud is live. Sign up free →
GuidesAI Agents — Writing effective binding rules

AI Agents — Writing effective binding rules

binding.reglas is where per-client behaviour lives — the tone of voice, the identity, the cancellation policy, the local quirks of a single customer of your platform. The system prompt from the AgentVersion stays the same across the whole tenant; reglas is the per-binding layer that lets one customer’s agent talk formally about “usted” and another one bounce with emojis and “¡buenísimo!” without cutting a new version.

This guide is the operational manual for that layer — extracted from a pilot iteration (v18 → v23) that surfaced every non-obvious way the LLM misreads reglas.

Runtime path (§17 F1.d): the ContextComposerService walks binding.reglas alphabetically and appends each key as a Markdown section (## [Humanized Key]\n\n[value]) into the system prompt, right after the tenant kernel and right before the runtime context. The LLM sees ## Tono\n\nformal — not tono: "formal".

The one rule that beats everything else

Write instructions, not keywords.

The LLM reads reglas as prose in the system prompt. It applies free-form English/Spanish text just fine. It does not reliably map short labels to behaviour, especially in small-tier models (gpt-4o-mini, claude-haiku, gemini-2.0-flash). This is the single biggest source of “why isn’t my binding changing anything?” tickets.

Concrete case from the Fitz Roy pilot:

// ❌ The bot's tone did not change at all
{
  "tono": "muy_cordial"
}
// ✅ Same intent, expressed as an instruction — took effect immediately
{
  "tono": "Muy cordial y cálido. Usá emojis (😊, ✨, 🙌) y expresiones como '¡buenísimo!', '¡qué gusto!', '¡genial!'. Saludá con energía."
}

The first version rendered as ## Tono\n\nmuy_cordial — an isolated label with no semantics attached. The second rendered as an actual instruction the model could apply verbatim.

Rule of thumb: read your value out loud. If it sounds like a config knob, rewrite it as a sentence you’d say to a new human hire.

Common keys and their shape

reglas is free-form JSON — you can put whatever your system prompt refers to. These are the keys that surface repeatedly in real pilots:

KeyPurposeExample
tonoVoice, register, emoji policy, pronoun (vos/usted/tú)“Formal, tratá de usted, sin emojis, evitá muletillas.”
identidadIAHow the agent handles being asked if it’s an AI”Aclará al inicio de la primera respuesta: ‘Soy el asistente virtual de [clínica]’. Si el paciente pregunta, respondé honestamente.”
nombreThe agent’s presentation name”Gesti (el asistente virtual del centro Fitz Roy).”
notasEspecificasAd-hoc per-client instructions”Los sábados no atendemos. Hay estacionamiento propio.”

Vertical-specific keys (invent whatever you need — the system prompt is the one that decides which keys it reads):

Healthcare

{
  "tono": "Cordial, tratá de vos. Emojis medidos.",
  "identidadIA": "Aclará que sos el asistente virtual solo si el paciente pregunta.",
  "politicaCancelacion": "Se puede cancelar hasta 24hs antes sin cargo. Después de esa ventana se pierde la seña si la hay.",
  "obrasSociales": "Trabajamos con OSDE, Swiss Medical, IOMA, PAMI y particular. Otras: derivar a recepción.",
  "preparacionPrevia": "Consultas generales: sin preparación. Estudios: informamos en el momento del confirmar.",
  "teleconsulta": "Disponible para clínica médica y psicología los martes y jueves de 15 a 19hs.",
  "derivaciones": "No hacemos derivaciones a otros centros — solo turnos con nuestros profesionales."
}

Support / customer service

{
  "tono": "Profesional directo. Sin muletillas, sin emojis excepto ✅ para confirmaciones.",
  "identidadIA": "Aclará al inicio: 'Soy el asistente virtual de [empresa], si prefieres hablar con una persona pedí escalamiento en cualquier momento.'",
  "escalationPolicy": "Escalá siempre que el cliente pida hablar con humano, o si detectás enojo/frustración explícita, o si el problema no está en el listado de FAQs conocidas.",
  "slaWindows": "Consultas técnicas: primera respuesta en <1h. Solicitudes de reembolso: derivamos a facturación (respuesta en 24-48hs hábiles)."
}

E-commerce

{
  "tono": "Amigable pero eficiente. Vos.",
  "identidadIA": "No mencionar salvo pregunta directa.",
  "refundPolicy": "30 días desde la fecha de compra con ticket. Sin ticket no se procesan reembolsos.",
  "paymentMethods": "Aceptamos MercadoPago, transferencia bancaria y tarjetas de crédito/débito.",
  "shippingWindows": "Envíos a domicilio 3-5 días hábiles. Retiro en sucursal: inmediato tras confirmación."
}

The anti-patterns you’ll trip over

1. Abstract labels instead of instructions

Already covered above — the single biggest failure mode. If the model isn’t changing behaviour when you set a reglas key, this is almost always the reason.

2. Vocabulary that trips the output-safety guardrail

The runtime blocks factual claims that no tool call backs. Words that trigger the block before a milestone tool succeeds:

  • reservé, agendé, confirmé tu turno, te anoté, dejé tu turno — matched by the reserve guardrail unless a tool whose slug contains reserv / crear_turno / agend returned ok=true in the current run.
  • cancelé tu turno — needs a cancel / eliminar_turno tool.
  • reprogramé, moví tu turno — needs a reprogram / update_turno / modif tool.

Do not put these words as instructions in reglas unless you know the tool will run first. In the pilot’s v22 the paso 6 said “para reservar necesito tu DNI” — the model faithfully replied with “reservar” before the reservation ran, and every message got silently blocked. Fix: use neutral verbs (coordinar el turno, sacar el turno, para continuar, para seguir) in every prompt step before the milestone tool.

3. Rules that contradict the AgentVersion system prompt

The system prompt from the AgentVersion and binding.reglas sit in the same context window. If they disagree, the model splits the difference in ways you didn’t design.

Bad: system prompt says “Tratá de vos (español rioplatense)”, reglas.tono says “Formal — usted.” Model alternates between “vos” and “usted” mid-conversation.

Good: the system prompt defers to reglas explicitly — “Tratá de vos por defecto, salvo que la sección ## Tono de las reglas del centro indique otra cosa.”

4. Runtime knobs in reglas (they belong in params)

reglas is read by the LLM as prompt text. It cannot change runtime behaviour. Kill switches, caps, wizard flags — all of those live in binding.params and are read by the agent engine, not the model.

If you put {"wizardEnabled": true} in reglas, the model just sees ## Wizard Enabled\n\ntrue in the prompt and confuses itself with what it means. Nothing turns on.

See the Rules vs Params vs Secrets table for what belongs where.

5. Stale history overriding a new prompt

When you change the AgentVersion system prompt on threads that already have accumulated messages, the old history acts as an implicit few-shot: the model reads its own previous replies as evidence of “how we respond around here”, and keeps doing it — even when the new prompt explicitly forbids it.

The pilot’s v18 → v22 iteration burned three hours on this. The prompt was fine; the thread just wouldn’t behave.

Three ways to clear the history:

  • Portal button/app/ai-agents/threads → “Reset conversation” per thread. Best while iterating on prompts.
  • Milestone tool — set terminates_thread: true on a tool declaration. See Milestone tools & auto-reset.
  • Automatic by inactivitybinding.params.inactiveResetDays (default 3). See Housekeeping — inactive thread reset.

Iteration workflow

Recommended loop when you’re refining reglas for a live binding:

Change the JSON

Edit binding.reglas in the portal or via PATCH /v1/agent-bindings/:id.

Reset the pilot thread’s history

/app/ai-agents/threads?all=1 → find the pilot thread → “Reset conversation”. Otherwise the model will keep replicating pre-change patterns.

Send a test message and check the events

/app/ai-agents/events?conversation_id=[pilot conv] → verify no output_safety block, no unexpected mute, and the milestone tool ran with ok=true (if applicable).

Read the log to see what the model actually rendered

Look at the latest AgentRun.systemPrompt to confirm your rule showed up as expected — ## Your Key\n\nyour value should appear near the top, between the kernel and the runtime context.

Cross-references