Оптимізація промптів для AI‑агентів (без поломки продакшену)

Як оптимізувати промпти без регресій: версіонування, регресійні тести, бюджети вартості/латентності й rollouts. Є Python + JS приклади.
На цій сторінці
  1. Проблема (той самий “маленький правочок”, який з’їдає тиждень)
  2. Чому це ламається в проді
  3. Діаграма: безпечний пайплайн промптів
  4. Реальний код: версіонуй промпти як код (Python + JS)
  5. Реальний фейл (з цифрами)
  6. Компроміси
  7. Коли НЕ оптимізувати промпти
  8. Copy‑paste чекліст
  9. Safe default config (YAML)
  10. Implement in OnceOnly (опційно)
  11. FAQ (3–5)
  12. Пов’язані сторінки (3–6 лінків)

Проблема (той самий “маленький правочок”, який з’їдає тиждень)

Ти підкручуєш промпт, бо агент звучав трохи дивно.

У dev усе норм.

У проді:

  • tool calls/run повзуть вгору (ніхто не помічає добу)
  • латентність подвоюється під навантаженням
  • агент починає “випадково” ігнорувати stop conditions
  • рідкісний edge case стає щоденним інцидентом

Оптимізація промпта — це інженерна робота, не “підбір слів”. Якщо робити це як “поміняю текст, поки не подобається” — ти зашиєш регресії в реліз.

Чому це ламається в проді

У проді промпт жорстко зчеплений з:

  • tool schemas (перейменував поле — модель “не розуміє”)
  • бюджетами (інфляція токенів робить лупи дорогими)
  • stop reasons (промпт може підштовхнути “ще одну спробу”)
  • варіативністю середовища (search дрейфує, API стають flaky, rate limits)

Неприємна правда: без harness’а промпти безпечно не оптимізуються. Harness не має бути складним. Він має бути стабільним.

Діаграма: безпечний пайплайн промптів

Реальний код: версіонуй промпти як код (Python + JS)

Мінімум, який реально має сенс:

  • кожен промпт має стабільний prompt_id (hash або версія)
  • кожен run логуває prompt_id
  • rollback — це один конфіг‑перемикач
PYTHON
import hashlib
from dataclasses import dataclass
from typing import Any, Dict


def prompt_id(text: str) -> str:
    return hashlib.sha256(text.encode("utf-8")).hexdigest()[:12]


@dataclass(frozen=True)
class Prompt:
    name: str
    version: str
    text: str

    @property
    def id(self) -> str:
        return f"{self.name}:{self.version}:{prompt_id(self.text)}"


class Logger:
    def event(self, name: str, fields: Dict[str, Any]) -> None: ...


def build_system_prompt(p: Prompt) -> str:
    return (
        "You are a production agent. You must follow tool policies and budgets.\n"
        "Always stop with a stop_reason.\n\n"
        f"[prompt_id={p.id}]\n"
        + p.text.strip()
    )


def run_agent(task: str, *, prompt: Prompt, logger: Logger, budgets: Dict[str, Any]) -> Dict[str, Any]:
    build_system_prompt(prompt)
    logger.event("agent_start", {"prompt_id": prompt.id, "budget": budgets})
    return {"output": "ok", "prompt_id": prompt.id, "stop_reason": "finish"}


PROMPTS = {
    "support:v12": Prompt("support", "v12", "Answer using KB. If unsure, ask a clarifying question."),
    "support:v13": Prompt("support", "v13", "Answer using KB. Cite tool results. If unsure, ask a clarifying question."),
}

ACTIVE_PROMPT = PROMPTS["support:v13"]
JAVASCRIPT
import crypto from "node:crypto";

export function promptId(text) {
  return crypto.createHash("sha256").update(text, "utf8").digest("hex").slice(0, 12);
}

export function makePrompt({ name, version, text }) {
  const id = `${name}:${version}:${promptId(text)}`;
  return { name, version, text, id };
}

export function buildSystemPrompt(prompt) {
  return [
    "You are a production agent. You must follow tool policies and budgets.",
    "Always stop with a stop_reason.",
    "",
    "[prompt_id=" + prompt.id + "]",
    prompt.text.trim(),
  ].join("\n");
}

export function runAgent(task, { prompt, logger, budgets }) {
  buildSystemPrompt(prompt);
  logger.event("agent_start", { prompt_id: prompt.id, budget: budgets });
  return { output: "ok", prompt_id: prompt.id, stop_reason: "finish" };
}

const PROMPTS = {
  "support:v12": makePrompt({ name: "support", version: "v12", text: "Answer using KB. If unsure, ask a clarifying question." }),
  "support:v13": makePrompt({ name: "support", version: "v13", text: "Answer using KB. Cite tool results. If unsure, ask a clarifying question." }),
};

const ACTIVE_PROMPT = PROMPTS["support:v13"];

Реальний фейл (з цифрами)

Ми “покращили” support‑промпт, додавши довгу інструкцію “будь максимально thorough”.

Нічого не впало. Але модель зробила те, що ми попросили: вона стала thorough.

Імпакт за 36 годин:

  • p95 tokens/run: 7.5k → 14.2k
  • avg tool calls/run: 4 → 11
  • витрати: +$620
  • онкол: ~2 години, щоб довести, що це промпт, а не трафік

Фікс:

  1. капнути бюджети (steps/tool calls/tokens)
  2. golden‑task інваріанти: max tool calls і max tokens
  3. “thoroughness” зробити умовним правилом (тільки коли tool result не вистачає)

Компроміси

  • Якість часто збільшує вартість. Якщо не вимірюєш — платиш.
  • Короткі промпти швидкі, але часто розмиті по safety.
  • Явні контракти не красиві, зате виживають.

Коли НЕ оптимізувати промпти

Не “оптимізуй промптом” те, що має бути інженерією:

  • бюджети (/uk/governance/budget-controls)
  • валідація tools (/uk/tools/input-validation)
  • логи (/uk/observability-monitoring/agent-logging)
  • тести (/uk/testing-evaluation/unit-testing-agents)

Якщо агент нестабільний — промпт‑тюнінг просто пересуває симптоми.

Copy‑paste чекліст

  • [ ] Стабільний prompt_id у логах кожного run’а
  • [ ] Golden tasks (10–50) з реального трафіку
  • [ ] Інваріанти: stop_reason, bound на tool_calls, bound на tokens
  • [ ] Canary rollout + швидкий rollback
  • [ ] Моніторинг: spend/run, tool_calls/run, latency/run
  • [ ] 1 golden task на кожен інцидент

Safe default config (YAML)

YAML
prompts:
  active: "support:v13"
  rollback: "support:v12"
  require_prompt_id: true
testing:
  golden_tasks:
    - id: "kb_lookup"
      expect_stop_reason: "finish"
      max_tool_calls: 6
      max_tokens: 9000
budgets:
  max_steps: 25
  max_tool_calls: 12
  max_seconds: 60
observability:
  log_prompt_id: true
  alert_on_token_spike: true

Implement in OnceOnly (опційно)

Implement in OnceOnly
Захисти промпт‑зміни бюджетами + stop reasons + логами.
Use in OnceOnly
# onceonly-python: budgets + safe rollout guardrails
import os
from onceonly import OnceOnly

client = OnceOnly(api_key=os.environ["ONCEONLY_API_KEY"])
agent_id = "support-bot"

# Set budgets/limits before you ship prompt changes
client.gov.upsert_policy({
    "agent_id": agent_id,
    "max_actions_per_hour": 200,
    "max_spend_usd_per_day": 50.0,
    "max_calls_per_tool": {"kb.search": 6},
    "allowed_tools": ["kb.search", "send_email"],
})

# After rollout, watch for spend/tool spikes
m = client.gov.agent_metrics(agent_id, period="day")
print("actions=", m.total_actions, "spend_usd=", m.total_spend_usd)

FAQ (3–5)

Чи варто A/B тестити промпти в проді?
Тільки якщо rollback миттєвий і ти моніториш spend/run та tool_calls/run. Інакше це просто керований інцидент.
Скільки має бути golden tasks?
Стартуй з 10–20 задач з реального трафіку. Додавай по 1 задачі на інцидент. Десь на 50 ти опинишся природно.
Що саме асертити в prompt‑тестах?
Stop reasons, кількість tool calls, budget stops і базові constraints. Не асерть точний текст.
Чи може промпт замінити guardrails?
Ні. Промпт змінює ймовірність. Guardrails змінюють те, що взагалі можливо.

Пов’язані сторінки (3–6 лінків)

⏱️ 4 хв читанняОновлено Бер, 2026Складність: ★★☆
Інтегровано: продакшен-контрольOnceOnly
Додай guardrails до агентів з tool-calling
Зашип цей патерн з governance:
  • Бюджетами (кроки / ліміти витрат)
  • Дозволами на інструменти (allowlist / blocklist)
  • Kill switch та аварійна зупинка
  • Ідемпотентність і dedupe
  • Audit logs та трасування
Інтегрована згадка: OnceOnly — контрольний шар для продакшен агент-систем.
Автор

Цю документацію курують і підтримують інженери, які запускають AI-агентів у продакшені.

Контент створено з допомогою AI, із людською редакторською відповідальністю за точність, ясність і продакшн-релевантність.

Патерни та рекомендації базуються на постмортемах, режимах відмов і операційних інцидентах у розгорнутих системах, зокрема під час розробки та експлуатації governance-інфраструктури для агентів у OnceOnly.