Notas prácticas: Un agente de soporte local con SmolLM3: Modo de pensamiento, herramientas y
Guía paso a paso operativa de las notas prácticas: Un agente de soporte local con SmolLM3: Modo de pensamiento, herramientas, y también contratos, verificaciones y espacios para código adicional para los equipos que implementan este patrón.
Úselo como una versión reestructurada dirigida a operadores de las ideas presentadas en “Un agente de soporte local con SmolLM3: modo de razonamiento, herramientas y cuándo no razonar”: etapas claras, espacios ordenados para el código y notas de recuperación que perduran tras la transferencia de tareas. La etapa de Resumen funciona mejor si se considera como una superficie medible. Capture una transcripción ejemplar, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace completaciones parciales silenciosas.
La configuración
En la fase de configuración, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Registre los tiempos de ejecución y el costo de tokens o consultas junto con los resultados funcionales. La visibilidad temprana del costo evita facturas inesperadas cuando el proceso pasa de entornos de demostración a entornos compartidos. Prefiera salidas estructuradas con validación de esquema sobre texto en formato libre cuando el siguiente paso sea escribir código o realizar una llamada a una herramienta.
Think vs no_think es una decisión del producto
En la etapa de decidir si pensar o no pensar, se deben definir las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Se debe mantener la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema. Se prefiere una salida estructurada con validación de esquema sobre texto libre cuando el siguiente paso sea un código o una llamada a una herramienta.
messages = [
{"role": "system", "content": "/no_think"},
{"role": "user", "content": prompt},
]
tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
enable_thinking=False, # the /no_think flag in the system prompt wins if both are set
)
<|im_start|>assistant
<think>
</think>
final = re.sub(r"<think>.*?</think>", "", raw, flags=re.DOTALL).strip()
<tool_call>
{"name": <function-name>, "arguments": <args-json-object>}
</tool_call>
TOOLS = [
{
"name": "lookup_order_status",
"description": (
"Look up the current status, estimated delivery date, and carrier "
"for a specific customer order. Call this when the customer mentions "
"an order number or asks where their order is."
),
"parameters": {
"type": "object",
"properties": {
"order_id": {
"type": "string",
"description": "The order ID, usually in the format ORD-XXXXXX.",
}
},
"required": ["order_id"],
},
}
]
ORDERS = {
"ORD-4821": {"status": "shipped", "eta": "June 18, 2026", "carrier": "DHL"},
"ORD-3307": {"status": "processing", "eta": "June 20, 2026", "carrier": None},
"ORD-1190": {"status": "delivered", "eta": None, "carrier": "FedEx"},
}
def respond_with_tools(user_message: str) -> str:
messages = [{"role": "user", "content": user_message}]
turn1 = generate_reply(messages)
name, args = parse_tool_call(turn1)
if name == "lookup_order_status":
result = lookup_order_status(**args)
messages += [
{"role": "assistant", "content": turn1},
{"role": "tool", "content": json.dumps(result), "name": name},
]
return generate_reply(messages)
return turn1
<tool_call>
{"name": "lookup_order_status", "arguments": {"order_id": "ORD-4821"}}
</tool_call>
El ticket por correo electrónico es donde muere el bucle ingenuo
En la etapa de los tickets por correo electrónico, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Prefiera salidas estructuradas con validación de esquema sobre texto libre cuando el siguiente paso sea escribir código o realizar una llamada a una herramienta. En la etapa de los tickets por correo electrónico, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas.
<tool_call>
{"name": "lookup_order_status", "arguments": {"order_id": "your_order_id"}}
</tool_call>
Protecciones que no se ajustan con fine-tuning
Al trabajar con las protecciones que no están en fase de desarrollo, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto a los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el camino pasa de la versión de demostración a entornos compartidos. Almacene en caché las instrucciones del sistema estables y los esquemas de herramientas. Reenviar un preámbulo idéntico es una causa común de consumo excesivo.
ORDER_RE = re.compile(r"^ORD-\d{4,}quot;)
PURE_TOOL_RE = re.compile(r"^\s*<tool_call>(.*?)</tool_call>\s*quot;, re.DOTALL)
def parse_executable_tool_call(output: str):
cleaned = re.sub(r"<think>.*?</think>", "", output, flags=re.DOTALL).strip()
match = PURE_TOOL_RE.match(cleaned)
if not match:
return None
payload = json.loads(match.group(1).strip())
order_id = str(payload.get("arguments", {}).get("order_id", "")).strip()
if not ORDER_RE.match(order_id):
return None
return payload
Lo que esto no demuestra
Al trabajar en la sección “Qué no incluye esta etapa”, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación ayuda a mantener honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de consumo excesivo.
Ejécutelo
Al trabajar en la fase de “Ejecutarlo”, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Documente tanto la ruta de éxito como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Almacene en caché las instrucciones estables del sistema y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de problemas. Al trabajar en la fase de “Ejecutarlo”, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Trate esta fase como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina las comprobaciones de éxito y rechace las completaciones parciales silenciosas.
python llm-learning/smollm3-local-support-agent/code/think_vs_nothink.py
python llm-learning/smollm3-local-support-agent/code/support_agent.py
python llm-learning/smollm3-local-support-agent/code/support_agent_guarded.py
Lista de verificación operativa
Al trabajar en la fase de lista de verificación operativa, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código.
Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado.
Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de problemas.
Exponga las herramientas con esquemas limitados y etiquetas claras sobre efectos secundarios. Los hosts necesitan saber qué llamadas modifican el estado antes de aprobarlas automáticamente.
Deje la aprobación humana para los casos en que se gastan fondos o se modifican datos de producción. La conexión en tiempo de compilación no equivale a la completitud del proceso empresarial.
Escriba un breve manual de operaciones: cómo rotar claves, cómo vaciar la cola y cómo revertir la última inserción.
Antes de promocionar la solución, congele las versiones, capture una transcripción de referencia para el camino crítico y confirme los pasos de reversión. Los entornos compartidos requieren límites de velocidad, verificaciones de tenencia y un responsable claro para la rotación de credenciales secretas. Prefiera una fiabilidad sencilla a demostraciones ingeniosas pero puntuales.
Nota para el lote 0e44ad944ff5: mantenga las claves del proveedor fuera del repositorio, establezca un límite para los tokens por sesión y almacene las transcripciones junto a los archivos de prueba para que los cambios posteriores en el modelo sigan siendo comparables.
Al trabajar en la nota de fortalecimiento de la etapa 0, anote primero el contrato: entradas requeridas, señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.
Detalle de reforzamiento 0/868: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.
La etapa 1 de las notas de reforzamiento funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance. Trate esta etapa como un contrato entre entradas y salidas validadas. Asigne nombres a los artefactos, defina verificaciones de éxito y rechace completaciones parciales silenciosas.
Detalle de reforzamiento 1/868: mida el tiempo de ejecución, la clase de error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.
Para la fase 2 de las notas de fortalecimiento, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema.
Detalle de fortalecimiento 2/868: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de criterios en lugar de en observaciones anecdóticas.
Al trabajar en la fase 3 de las notas de fortalecimiento, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando un paso falla, el fallo debe apuntar a una única responsabilidad y no a un proceso complicado.
Detalle de fortalecimiento 3/868: mida el tiempo de ejecución, la clase del error y el consumo de tokens para esta nota, y luego decida si mantener el cambio basándose en un conjunto fijo de preguntas en lugar de en anécdotas.