Галоўная / Артыкулы / Практычныя прытамулкі: Інжынерыя циклаў: стварэнне самапраграсных агентаў ШІ з чатырма элементамі

Практычныя прытамулкі: Інжынерыя циклаў: стварэнне самапраграсных агентаў ШІ з чатырма элементамі

Практычныя прытамулкі: Інжынерыя циклаў: стварэнне самапраграсных агентаў ШІ з чатырма элементамі – кантрактамі, пераказамі та слотамі для коду, якія можна выкарыстоўваць командам, якія реалізуюць гэты патэрн.

7704 слоў

Існавайце гэта як перапрацоўаны варыянт ідэй з кніги «Loop Engineering: Building Self-Improving AI Agents with Four Nested Loops» для аператараў: чыткія этапы, аранжаваныя блакі коду і прыметкі з восстанавлення, якія застаюцца пасля перадачы. Этап «Агульны аптак» найэфектывнейша працюе, калі яго розглядаць як вимерную паверхню. Запісаўце адна ідеальная транскрыпцыя, адзін прыклад неудачы і прыметкі з вярнення да пачатковага стану прычым расшырэнню масштаба. Зберагайце настройкі праза код аплікацыі. Файлы сяродавішча, хранільнікі секрэтных дадзеных і флагі функций павінны знаходзіцца ў адном месцы, якое аператары можаць пераглядаць без неабяжнага чытання всіх элементаў.

Разбор загальнай кантэксту: інжынерыя за межамі запитаў

Для стадіі «Разбор загальнай карты» неабяжна практычна апранаванне: перад тым, як зменіць код, трэба чыткая апрацаваць вхідныя даны, адпаведальнага за крок і критэрыя завершэння. Аперацыямі трэба быць можлівасць практычна запускаць крок з вядомага контрольнага пункту, не спрабоўваючы здогадвацца пра схованы стан. Неабяжна аддзеўнаваць як «шчаслівы» шлях, так і шлях вярнення. Практычна запускі, людзкія перакрыцця і обробка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней. Калі наступны крок — це код або вызов інструмента, лепш выкарыстоўваць структураваныя выходныя даны з перакрыцчама схемы, чым вольныя тэкстовыя апісанні.

Чаму гэта важна

У раздзеле «Чаму гэта важна» неабяжно задаць даныя, якія будуць вводзіцца, адпаведальнага за выкананне крока, а таксама критэрыя завершэння пры зміне коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю, не прабуючы спадарацца прыватны стан. Лепш выбіраць маленькія, тэставаныя елементы заместо велікіх скрыптав. Калі крок не выйшоў, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны процес. Неабяжна працаваць з апраўданнем чалавека ў тых моментах, калі выконваюцца витраты або зменяюцыся даныя для працы. Компіляцыйны механізм не є адпаведным для падтрымкі полнай структуры бізнес-процэсаў.

Асновная ідея: вёсканыя ціклы керування

Для стадіі The Core Idea Nested неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры перадзмене коду. Аперацыйныя працавнікі должны магчымае перайсці на выкананне кроку з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Спрацавляйце з гэтай стадіяй як з кантрактом межаў вхідных дадзеных і перакананых выходных рэзультатаў. Даць назвы артыфактам, узначыць пераказы успеху і адмовіцца ад беззвучнага частковага завершэння. Заставіць людзкую апраўду на тых элементах, якія витрачаюць грошы або зменяюць даны для працы. Прыўязка ў часе компілявання не адпавядае пачатковай цэлесообразнасі працы. Для стадіі The Core Idea Nested неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры перадзмене коду. Аперацыйныя працавнікі должны магчымае перайсці на выкананне кроку з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Зберагачыце настройкі параду ад коду прыемленае. Файлы сяродавішча, хранільнікі секрэтных дадзеных і флагі функцыйяў должны знаходзіцца ў аднам месцы, якое працавнікі можуць аудытаваць, не чытаючы весь ланцуг.

┌──────────────────────────────────────────────────────┐
│  Loop 4 — Hill Climbing (self-improvement over time) │
│  ┌────────────────────────────────────────────────┐  │
│  │  Loop 3 — Event Queue Poller (orchestration)   │  │
│  │  ┌──────────────────────────────────────────┐  │  │
│  │  │  Loop 2 — Verification & Retry           │  │  │
│  │  │  ┌────────────────────────────────────┐  │  │  │
│  │  │  │  Loop 1 — ReAct Agent              │  │  │  │
│  │  │  │  (think → act → observe → think)   │  │  │  │
│  │  │  └────────────────────────────────────┘  │  │  │
│  │  └──────────────────────────────────────────┘  │  │
│  └────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘

Домэн: Акцэптаванне страховых практык

Калі працуеце на стадзіі акцэптавання страховых практык, спачатку запісайце контракт: неабяжлівыя даны, сігнал успеху і тое, што выканаецца у разе частковага нявыполнення. Такі список пераканальвае застаўляцца чыстасцю пазнейшых змян у кодзе. Документавайце як шлях успеху, так і шлях вярнення да нормы. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў ёсць частью продукту, а не пазнейшым дапрацоўкам. Зробіце пераканальну пазначку пасля дорогіх крокаў. Програма не должна занова выклікаць той самы LLM-кал, калі аператар перапрыбуе пазнейшы вузел.

{
  "id": "APP-001",
  "applicant_age": 34,
  "state": "FL",
  "property_type": "residential",
  "coverage_amount": 450000,
  "claim_history_5yr": 1,
  "credit_score_tier": "good",
  "flood_zone": true,
  "has_flood_rider": false,
  "business_use": false
}
"APP-001": {
  "split": "train",
  "expected_decision": "modify",
  "expected_flags": ["flood_rider_required", "windstorm_exclusion"]
}

Цікл 1: Агент ReAct

Калі працуеце над стадзіяй Loop 1 The ReAct, спачатку запісайце умовы працы: неабяжлівыя даны, сигнал успеху і тое, што выходзіць пад частыя неудачы. Такі список контролю дапамагае залічваць змяны ў кодзе чыста. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, неудача должна вказваць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Зробіце перапактаванне пасля дорогіх крокаў. Програма не должна зноў ставіць плату за той самы вызов LLM, калі аператар праказвае спробу ў вынікуючым вузле.

Шаблон

Калі працуеце над стадзіяй «The Pattern», спачатку запісайце контракт: неабяжлівыя даннэ, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список перакладзець пазнейшыя змены коду ў правільныя рамкі. Спрыймайце гэтую стадзію як контракт межа даннемі і перакананымі выходамі. Дайце назву кожнам элементам, задаце критэрыя успеху і не падзволяйце частковаму завершэнню без паведамлення. Зрабіце перапактаванне пасля дорогіх крокаў. Програма не должна зноў выклікаць той самы LLM-званак, калі аператар прабуе зноў запрацаваць з пазнейшым вузлам. Калі працуеце над стадзіяй «The Pattern», спачатку запісайце контракт: неабяжлівыя даннэ, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список перакладзець пазнейшыя змены коду ў правільныя рамкі. Зберагачыце настройкі парадульна ад коду прыемліцеля. Файлы сераў, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, куда аператары можу працаваць без неабяжлівага чытання всей структуры.

System Prompt
     │
     ▼
[Think] → What information do I need?
     │
     ▼
[Act]   → Call tool (lookup_application, retrieve_rules, ...)
     │
     ▼
[Observe] → Tool returns result
     │
     ▼
[Think] → What does this mean? What next?
     │
    ... (repeat until decision is made)
     │
     ▼
[Act]   → draft_decision (terminal tool call)

Адкалекаванне LangGraph

Этап рэалізацыі LangGraph працуе наякша, калі яго спрыяваць як мерыемую паверхню. Зафіксавце адны ідеальны прыклад работы, адну ситуацыю неудачы і прыметкі па адвярненню перад расшырэнням масштаба. Дакументавайце як шлях успеху, так і шлях вярнення да нормальнага стану. Перапрыбуткі, людзкія контраліны і обработка некоректных паведамленняў є часткай продукту, а не элементамі пазнейшай дапрацоўкі. Храніце стан графа у простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спаказваюць працу пасля перарываў.

class UnderwritingState(TypedDict):
    application_id: str
    messages: Annotated[list[AnyMessage], add_messages]  # reducer accumulates
    decision: str
    rationale: str
    flags: list[str]
    recommended_premium_adj: float
    lessons: list[str]
    spend: float
    _steps: int
def build_loop1(system_prompt: str, meter: CostMeter):
    model = ChatAnthropic(model="claude-sonnet-4-6").bind_tools(TOOLS)
    def agent_node(state: UnderwritingState) -> dict:
        prompt = system_prompt
        if state.get("lessons"):
            prompt += "\n\nUnderwriting lessons:\n" + "\n".join(
                f"- {l}" for l in state["lessons"]
            )
        msgs = [SystemMessage(content=prompt)] + list(state["messages"])
        response = model.invoke(msgs)
        meter.record_from_message(response)          # track spend per call
        return {
            "messages": [response],
            "_steps": state.get("_steps", 0) + 1,
            "spend": meter.spent,
        }    def tools_node(state: UnderwritingState) -> dict:
        last = state["messages"][-1]
        tool_results, updates = _dispatch_tools(last.tool_calls)
        return {"messages": tool_results, **updates}  # updates captures draft_decision output    def should_continue(state) -> Literal["tools", "__end__"]:
        if state.get("_steps", 0) >= MAX_STEPS:   # hard cap at 8 steps
            return END
        if getattr(state["messages"][-1], "tool_calls", None):
            return "tools"
        return END    g = StateGraph(UnderwritingState)
    g.add_node("agent", agent_node)
    g.add_node("tools", tools_node)
    g.set_entry_point("agent")
    g.add_conditional_edges("agent", should_continue, {"tools": "tools", END: END})
    g.add_edge("tools", "agent")
    return g.compile()

Чатыры інструменты

Этап «Чатыры інструмента» працюе найэфектывней, калі яго розглядаць як вимерную паверхню. Зафіксавце адна «золатая» транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштабы. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына неудачы павінна вказываць на адну конкрэтную адпаведнасць, а не на заплутаны ланцюг задач. Актуалізавайце інструменты з вузкімі схемамі та чысткімі пазначэннямі побачных наследкаў. Адпаведальныя особы павінны знать, якія вызовы мутуюць стан, перш чым автаматычна схваліць іх.

@tool
def lookup_application(app_id: str) -> dict:
    """Return the full application record for the given application ID."""
    # reads from applications.json — deterministic, no LLM call
@tool
def retrieve_rules(risk_factor: str) -> list[str]:
    """Return underwriting rules matching the given risk factor keyword.
    Use terms like: flood, claims, credit, coverage, state, business."""
    # keyword match against rules_kb.json - forces explicit rule lookup
@tool
def fetch_risk_signal(signal_type: str) -> dict:
    # simulated external data pull (credit bureaus, flood maps, etc.)
@tool
def draft_decision(
    decision: Literal["accept", "modify", "decline", "refer"],
    rationale: str,
    flags: list[str],
    recommended_premium_adj: float,
) -> dict:
    """Finalize the underwriting decision with structured output."""
    # terminal action - structured schema forces the agent to commit explicitly

Чаму важна меры для крокаў

Этап «Прычына і ліміт крока» працюе найэфектывней, калі яго спрыяваць як меравальную паверхню. Зберагчыце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць сферу дзеяння. Спрыявайце гэты этап як кантракт межа вхіднымі даннымі і пераканаленымі выходнымі рэзультатамі. Даўце назвы артыфактам, задаце критэрыя успеху і адмовіцеся ад тых падзеяў, калі задача выканана часткова без паведамлення. Храніце стан графа ў простым і типаванам формате. Вярнутыя структуры данных маскуюць інфармацыю пра тое, який вузел запісаў кожны поле, і спаказваюць продажчэнне выканання пасля перарываў. Этап «Прычына і ліміт крока» працюе найэфектывней, калі яго спрыяваць як меравальную паверхню. Зберагчыце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць сферу дзеяння. Храніце настройкі параду ўнутры коду прыемлівача. Файлы сяродавішча, базы секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куда аператары можу аудытаваць іх без неабходнасці чытаць весь граф.

Цикл 2: Аверыяцыя і прабныя спробы на адной засаде градэра

Для верыфікацыі та наступных этапаў Loop 2 неабходна прадзефінаваць вхідныя даны, адпаведальную особу за кожны крок і крэтарыя выходу пры змены коду. Аператары должны магчымае перзапускати крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Неабходна задокументаваць як шлях успеху, так і шлях вярнення да нормальнага стану. Перапрыбуткі, людзкія пераказы та обработка некоректных паведамленняў є часткай продукту, а не елементамі пазнейшага доўнелення. Неабходна людзкая затверджэння для тых крокаў, якія ведуць да выдаткаў грошаў або зміняюць даны ў працэсе виробніцтва. Працэсы, якія выкананы ў часе компіляцыі, не є падставай для стверджэння повнасці продукту з точкі зору бізнес-патрэбаў.

def run_loop2(
    app_id: str,
    system_prompt: str,
    meter: CostMeter,
    max_retries: int = 3,
) -> tuple[dict, bool]:
    state = run_loop1(app_id, system_prompt, meter)
for attempt in range(max_retries):
        decision = state.get("decision", "ran_out_of_steps")
        if decision == "refer":
            _write_human_queue(app_id, state)   # human-in-the-loop path
            return state, True
        if is_correct(decision, app_id):         # deterministic check
            return state, True
        if attempt >= max_retries - 1:
            return state, False                  # exhausted retries
        # construct targeted feedback for next attempt
        expected = load_historical_decisions()[app_id]["expected_decision"]
        feedback = HumanMessage(content=(
            f"Your decision was '{decision}' but this application requires '{expected}'. "
            f"Review the risk factors carefully and call draft_decision again."
        ))
        extra_messages = list(state.get("messages", [])) + [feedback]
        state = run_loop1(app_id, system_prompt, meter, extra_messages=extra_messages)
    return state, False

Рашэнняя па дызайне, якія варта адзначыць

У стадії «Рашынкі ў дзялянцы дизайна», якія вартае адзначыць, перш чым зменяць код, неабходна визначыць вхідныя даны, адпаведальнага за шаг і критэрыя завершэння. Аператары должны магчымаць перзапуск шага з вядомай точкі контролю, не спрабоўваючы здогадвацца пра схованы стан. Валіць кращэ маленькія, тэставаныя елементы за велікія скрыпты. Калі шаг не выйшаў, прычына неудачы должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны процес. Неабходна людская апраўда для тых крокаў, якія выкалічваюць грошы або зменяюць даны ў працэсе. Компіляцыйныя налашчэння не є прамаравамым паказателем завершання бізнес-процэса.

Цыкл 3: Апарат для перагляду календара запускаў

Для стадіі Loop 3 The Event неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя выходу пры перадзеі коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю без адгадвання захаванага стану. Спрыяйце цій стадіі як кантракту межаў вхідных дадзеных і перакананых выходных рэзультатаў. Даць назвы артыфактам, узначыць перакананні ў успеху і адмовіцца ад тыхняга частковага завершэння без паведамлення. Заставіць людзкую апраўдку для тых крокоў, якія выкарыстоўваюць грошы або зменяюць даны ў працэсе. Компіляцыйныя налашчанні не ўзначаюць павнае завершэння бізнес-процесу. Для стадіі Loop 3 The Event неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя выходу пры перадзеі коду. Аператары должны магчымаць перзапуск крока з вядомай точкі контролю без адгадвання захаванага стану. Зберагачыце налашчанні за межамі коду прыкладнення. Файлы сераў, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнага чытання всіх элементаў.

def run_event_loop(
    system_prompt: str,
    meter: CostMeter,
    pending_path: Path = DEFAULT_PENDING,
    state_path: Path = DEFAULT_STATE,
    once: bool = False,
) -> None:
    run_state = load_run_state(state_path)
    verify_judge_checksum(run_state.get("judge_checksum", ""))   # tamper check
total = len(json.loads(pending_path.read_text(encoding="utf-8-sig"))
                if pending_path.exists() else [])
    processed = 0
    while True:
        pending = (json.loads(pending_path.read_text(encoding="utf-8-sig"))
                   if pending_path.exists() else [])
        if not pending:
            if once:
                print("[loop3] queue empty - done")
                break
            print("[loop3] queue empty - sleeping...")
            time.sleep(POLL_INTERVAL)
            continue
        app_id = pending[0]
        processed += 1
        print(f"[loop3] {processed}/{total}  {app_id} ...", flush=True)
        try:
            result_state, passed = run_loop2(app_id, prompt_with_lessons, meter)
        except BudgetExhaustedError:
            raise                                # budget exhaustion is fatal
        except Exception as exc:
            print(f"[loop3] {app_id} ERROR: {exc!r} - skipping")
            # remove from queue and continue - one bad app cannot block the rest
            remaining = [x for x in pending if x != app_id]
            pending_path.write_text(json.dumps(remaining), encoding="utf-8")
            continue
        # ... update state, distill lesson, trigger hill-climbing

Чаму файлавая абарантка?

Калі працуеце над этапам «Чаму файлавая абарантка?», спачатку запісайце умовы викорыстання: неабяжлівыя даны, сигнал працэсу, і што выканаецца у разе частковага невыпалення. Такі список контролю дапамагае заліцьварыць пазнейшыя змены ў кодзе. Документавайце як правільны, так і альтернатыўны шляхы виконання. Практыка павторных спроб, людзкі контроль і обработка некоректных паведамленняў є частью самага продукту, а не пазнейшых дапрацоўкаў. Стварайце контрольныя пункты пасля дорогіх крокаў. Система вярнення роботы не должна занова ставіць плату за той самы вызов LLM, калі аператар павторна працюе з пазнейшым вузлом.

Адкрыцье пазусаблівых змян за дапамогою сумы контролю

Калі працюеце над стадзіяй адказвання на пазускі праварыння за дапамою чэксума, спачатку запішыце умовы працы: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага праварыння. Такі список контролю дапамагае заліцьварыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, праварынне должна паказваць на адную адпаведальнасць, а не на заплутаны ланцужок задач. Зробіце контрольны пункт пасля дорогіх крокаў. Програма не должна зноў выклікаць той самы календар LLM, калі аператар праказвае пазнейшы вузел.

verify_judge_checksum(run_state.get("judge_checksum", ""))
def compute_judge_checksum() -> str:
    content = _HIST.read_bytes()           # historical_decisions.json
    return hashlib.sha256(content).hexdigest()
def verify_judge_checksum(expected: str) -> None:
    actual = compute_judge_checksum()
    if actual != expected:
        raise RuntimeError(
            f"Judge checksum mismatch - historical_decisions.json was tampered with."
        )

Адкладэнне працы проты зупінкі

Калі працуеце над стадзіяй «Адскаканне» проты «Злам», спачатку запісайце кантракт: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага зламу. Такій чэк-ліст дапамагае заставіць пазнейшыя змены коду быць чыстымі. Спрэтавайце гэту стадзію як кантракт межа даннімі і перакананымі выходамі. Дайце назву артыфактам, задаць тэсты на успех і не прабуйце прыймаць часткова завершанне без паведамлення. Зробіце чэкпоінт пасля дорогіх крокаў. Система вярнення не павінна зноў ставіць плату за той самы вызов LLM, калі аператар прабуе зноў запрацаваць пазнейшы вузел. Калі працуеце над стадзіяй «Адскаканне» проты «Злам», спачатку запісайце кантракт: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага зламу. Такій чэк-ліст дапамагае заставіць пазнейшыя змены коду быць чыстымі. Зберагайце настройкі за межамі коду прыемлівача. Файлы сераўнавання, хранільнікі секрэтных дадзенняў і флагі функций павінны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжлівага чытання всей структуры.

Цікл 4: Адбіранне на высоту (Самапрацоўка)

Этап падыння на хылі Loop 4 работае найкраща, калі яго розглядаць як вимерную паверхню. Запісаўце адна «золатая» транскрыпцыя, адин прыклад неудачы і запіс пра вярненне да пачатковага стану перш чым расширваць масштабы. Дакументаваце як шлях успеху, так і шлях вяснавання проблемы. Перапрыбуткі, людзкія контрольныя пункты і обработка некоректных паведамленняў є частью продукту, а не наступным этапам дорабкі. Храніце стан графаў у простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакшуюць продовжэнне роботы пасля перарываў.

seed prompt
     │
     ▼
evaluate on training set → score, failures
     │
     ▼
┌────────────────────────────────┐
│  for each round:               │
│                                │
│  reflect(current, failures)    │  ← LLM analyzes failure patterns
│       │                        │
│       ▼                        │
│  candidate_prompt              │
│       │                        │
│       ▼                        │
│  evaluate(candidate, train)    │  ← full eval run
│       │                        │
│       ▼                        │
│  audit_prompt(candidate)       │  ← anti-cheating check
│       │                        │
│       ▼                        │
│  if score > best AND clean:    │
│      best = candidate          │  ← keep
│  else:                         │
│      discard                   │  ← revert
└────────────────────────────────┘
     │
     ▼
write best_prompt.txt

Этап аналізу

Этап «Reflection Step» працюе найкраща, калі яго розглядаць як вимерную паверхню. Запісаце адна «золатая» транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына неудачы павінна вказваць на адну конкрэтную адпаведнасць, а не на заплутаны ланцюг задач. Рэзультаты роботы графа павінны быць простымі та з адначытаемым типам. Вкладзеныя структуры маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакоююць продовжэнне роботы пасля перерываў.

REFLECT_TEMPLATE = """You are improving the system prompt of an insurance underwriting agent.CURRENT PROMPT:
{prompt}
The agent got these decisions WRONG on training applications:
{failures}
Look for PATTERNS in the failures. Infer GENERAL underwriting rules that would fix them.
Do NOT memorize specific application IDs or applicant details.
Write an improved system prompt. Reply with ONLY the new prompt text."""
def reflect(current_prompt: str, failures: list[dict]) -> str:
    client = anthropic.Anthropic()
    failure_text = "\n".join(
        f"- APP {f['app_id']}: agent said '{f['got']}', expected '{f['expected']}'. "
        f"Application data: {f['application']}"
        for f in failures
    )
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1500,
        messages=[{"role": "user", "content": REFLECT_TEMPLATE.format(
            prompt=current_prompt,
            failures=failure_text,
        )}],
    )
    return response.content[0].text.strip()

Этап «Evaluation Step»

Этап «Адзэнкаў» працюе наякша, калі яго спрыяваць як мерыемую паверхню. Зберажыце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць сферу дзеяння. Спрыяйце гэтам этапу як кантракту межа вхіднымі даннымі і перакананымі выходнымі рэзультатамі. Даць назвы артыфактам, задаць критэрыя успеху і адмовіцца ад тыхняе частковага завершэння без паведамлення.

def evaluate_prompt(system_prompt: str, split: str = "train", meter=None):
    tasks = load_tasks(split)
    failures = []
    for task in tasks:
        state = run_loop1(task["id"], system_prompt, meter)
        decision = state.get("decision", "ran_out_of_steps")
        if not is_correct(decision, task["id"]):
            failures.append({
                "app_id": task["id"],
                "got": decision,
                "expected": task["expected_decision"],
                "application": task["application"],
            })
    score = (len(tasks) - len(failures)) / len(tasks)
    return score, failures

Этап «Адзэнкаў» працюе наякша, калі яго спрыяваць як мерыемую паверхню. Зберажыце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць сферу дзеяння. Зберагаюце настройкі за межамі коду прыемлівача. Файлы сераўнавання, хранільнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнага чытання всіх дадзеных.

Бар’ер: Захопленне ад чрэзмернага прылегласця і захопленне ад шахрайства

Для функцыі The Gate проты перэзапрашвання і наступных етапаў неабходна пазначыць вхідныя даны, адпаведальнага за кожны крок і крэтарыя выходу пры перадзмене коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не прабуючы спадарожваць схованы стан. Неабходна аддзеўнаваць як шлях успеху, так і шлях вяснавання проблем. Перапрыбуткі, людзкія пераказы і обработка некоректных паведамленняў є часткай продукту, а не яго пазнейшай дапрацоўкі. Пры выкарыстоўванні грошэй чы змяне дадзеных у працэсе виробніцтва неабходна людзкая затверджэння. Працэсы, якія выконваюцца пад час компілявання, не є гарантыяй полнай адпаведнасці продукту бізнес-трэбованням.

def improve(seed_prompt: str, lessons: list[str], meter: CostMeter, rounds: int = 5) -> str:
    best = with_lessons(seed_prompt, lessons)
    best_score, failures = evaluate_prompt(best, split="train", meter=meter)
for r in range(1, rounds + 1):
        candidate = reflect(best, failures)
        score, cand_failures = evaluate_prompt(candidate, split="train", meter=meter)
        verdict = audit_prompt(candidate)        # anti-cheat check
        if score > best_score and verdict == "VERDICT: CLEAN":
            best, best_score, failures = candidate, score, cand_failures
            BEST_PROMPT_PATH.write_text(best, encoding="utf-8")
            print(f"round {r}: {score:.0%} KEPT  ({len(cand_failures)} failures)")
        else:
            reason = "cheating" if verdict != "VERDICT: CLEAN" else f"{score:.0%} <= {best_score:.0%}"
            print(f"round {r}: {score:.0%} REVERTED ({reason})")
    return best

The Prompt Auditor

Для стадіі The Prompt Auditor неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтыры завершэння пры змяне коду. Аперацыйныя працавнікі павінны магчымае перазапускаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшоў, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Калі наступным крокам є код або вызов інструменту, лепш выкарыстоўваць структураваныя выходныя даны з пераканальваннем схэмы, замест вольнага формата тэксту.

AUDIT_SYSTEM = (
    "You are a security auditor for AI systems. "
    "Check whether the prompt contains any hardcoded application IDs (e.g. APP-001) "
    "or hardcoded decisions for specific applications. "
    "These would constitute cheating — memorizing answers instead of learning rules. "
    "Reply with exactly one of:\n"
    "VERDICT: CLEAN\n"
    "VERDICT: CHEATING\n"
    "Followed by a one-sentence explanation."
)
def audit_prompt(evolved_prompt: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=200,
        system=AUDIT_SYSTEM,
        messages=[{"role": "user", "content": f"PROMPT TO AUDIT:\n{evolved_prompt}"}],
    )
    return response.content[0].text.strip().split("\n")[0]   # first line only

Памяць урокаў: Дыстыляцыя знанняў між сесіямі

Для стадіі «Пам’ять уроку: знання між сесіям» неабяцо пазначыць вхідныя даны, адміністратара крока і крэтырыя для завершэння пры перадзмене коду. Аперацыйныя працавнікі должны магчымаць перзапуск крока з вядомай точкі контролю без неабяцовага адгадвання захаванога стану. Спрыяць гэтай стадіі як кантракту межа вхіднымі данымі і падтвердзенымі выходнымі рэзультатамі. Даць назвы артыфактам, пазначыць крэтырыя успеху і адмовіцца ад беззвучнага частковага завершэння. Забезпечыць людзкія апраўджэння для тых крокаў, якія выкарыстоўваюць грошы або зміняюць даны праўай працы. Кампіляцыйныя налашчэння не ўзроўнаўцуюцься з пачатковай цэласнасцю бізнес-процэсу. Для стадіі «Пам’ять уроку: знання між сесіям» неабяцо пазначыць вхідныя даны, адміністратара крока і крэтырыя для завершэння пры перадзмене коду. Аперацыйныя працавнікі должны магчымаць перзапуск крока з вядомай точкі контролю без неабяцовага адгадвання захаванога стану. Зберагчыць налашчэнні за межамі коду прыкладнення. Файлы сераўіса, хранільнікі секрэтных данных і флагі функций должны знаходзіцца ў аднам месцы, якое працавнікі можуць аудытаваць.

Не трэба чытаць весь граф.

DISTILL_PROMPT = """An insurance underwriting agent made a wrong decision.Application details: {application}
Agent decided: {got}
Correct decision: {expected}
Write ONE short, general underwriting rule that would prevent this mistake.
Do NOT reference this specific application ID or any applicant names/details.
Reply with only the rule, as a single sentence."""
def distill_lesson(application: dict, got: str, expected: str) -> str:
    response = client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=150,
        messages=[{"role": "user", "content": DISTILL_PROMPT.format(...)}],
    )
    return response.content[0].text.strip()
def with_lessons(base_prompt: str, lessons: list[str]) -> str:
    if not lessons:
        return base_prompt
    lessons_text = "\n".join(f"- {l}" for l in lessons)
    return base_prompt + f"\n\nUnderwriting lessons learned:\n{lessons_text}"
def measure_gain(base_prompt: str, lessons: list[str], split: str = "test", meter=None) -> float:
    stateless_score, _ = evaluate_prompt(base_prompt, split=split, meter=meter)
    augmented = with_lessons(base_prompt, lessons)
    stateful_score, _ = evaluate_prompt(augmented, split=split, meter=meter)
    return stateful_score - stateless_score   # positive = lessons help

Контроль бюджэту: Памятак виткоў

Калі працуеце над этапам Контролю бюджэту: Памятак виткоў, спачатку запісайце контракт: неабходныя даны, сигнал успеху і тое, што выканаецца у разы частковага невяснення. Такі список пераканаець у тым, што пазнейшыя змены коду буду чыстымі. Запісуйце адночасна шлях успеху і шлях вяснення. Перапрыбуткі, людзкія контрольныя пункты і обработка некоректных паведамленняў ёсць частью продукту, а не пазнейшым дапрацоўкам. Ствараюце контрольныя пункты пасля дорогіх крокаў. Продовжэнне работы не должна знову выклікаць той самы календарны вызов LLM, калі аператар перапрыбуе пазнейшы вузел.

BUDGET_USD = 2.00
INPUT_PRICE_PER_TOKEN  = 3.00  / 1_000_000
OUTPUT_PRICE_PER_TOKEN = 15.00 / 1_000_000
class CostMeter:
    def record(self, input_tokens: int, output_tokens: int) -> None:
        if self.spent >= self._budget:              # check BEFORE adding
            raise BudgetExhaustedError(
                f"Budget ${self._budget:.2f} exhausted at ${self.spent:.4f}"
            )
        self.spent += input_tokens * INPUT_PRICE_PER_TOKEN \
                    + output_tokens * OUTPUT_PRICE_PER_TOKEN

Стан запуску: Ідэмпатная ініцыялізацыя

Калі працуеце над стадзіяй «Ідэмпатентная ініцыяцыя стану запуску», спачатку запісайце умовы працы: неабяжлівыя даннэ, сігнал успеху і тое, што выходзіць пад частыя неудачы. Такі список контроля дапамагае заліцвачыць пазнейшыя змены ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, неудача должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Зрабіце перапактаванне пасля дорогіх крокаў. Програма для продакцыі не должна зноў выклікаць той самы календар вызову LLM, калі аператар праказвае пазнейшы вузел.

def _init_run_state() -> dict:
    path = _STATE_DIR / "run_state.json"
    state = {}
    if path.exists():
        try:
            content = path.read_text(encoding="utf-8-sig").strip()  # handles Windows BOM
            if content:
                state = json.loads(content)
        except (json.JSONDecodeError, UnicodeDecodeError):
            pass                                 # corrupt file → start fresh
    if not state:
        state = dict(_DEFAULT_RUN_STATE)
    state["judge_checksum"] = compute_judge_checksum()   # always refresh
    path.write_text(json.dumps(state, indent=2), encoding="utf-8")
    return state

Тры режымы запуску

Калі працуеце над стадзіяй «Тры спосабы запуску», спачатку запісайце контракт: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Спрэчвайце гэтую стадзію як контракт межа даннімі і перакананымі выходамі. Дайце назвы артыфактам, задаць тэсты на успех і не падзеўляйце частковым завершэнням без паведамлення. Зробіце контрольную точку пасля дорогіх крокаў. Програма не должна зноў выклікаць той самы LLM-запуск, калі аператар прабуе зноў запрацаваць пазнейшы вузел. Калі працуеце над стадзіяй «Тры спосабы запуску», спачатку запісайце контракт: неабяжлівыя данні, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Зберагачыце настройкі за межамі коду прыемлівання. Файлы сераўнавальнага сяродавішча, хранілішчы секрэтных дадзенняў і флагі функций должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжлівага чытання всей структуры.

python -m src.main --mode single --app-id APP-001
python -m src.main --mode event-loop --once
python -m src.main --mode improve --rounds 5

Тэкучасць дадзейнаў: адпрацоўка па цэлай лініи

Этап адпрацоўкі тэкучасці дадзейнаў па цэлай лініи работае наякша, калі яго спрыймаюць як мерыемую структуру. Перш чым расширваць масштаб, зафіксавайце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану. Дакументавайце як шлях успешнай роботы, так і шлях вярнэння да нормальнага стану разам. Перапрыбуткі, людзкі контроль і обработка некоректных паведамленняў є часткай продукту, а не элементамі пазнейшай дапрацоўкі. Храніце стан графа ў простам і типаваным формате. Вярнутыя структуры дадзейнаў маскуюць інфармацыю пра тое, який вузел запісаў кожнае поле, і спакшуюць возз'яднанне пасля перерываў.

pending_applications.json
          │
          │  [Loop 3 reads APP-009]
          ▼
    run_loop2("APP-009", prompt, meter)
          │
          │  [Loop 2 calls Loop 1]
          ▼
    run_loop1("APP-009", prompt, meter)
          │
          │  [LangGraph StateGraph]
          ▼
    agent_node → ChatAnthropic.invoke([SystemMsg, HumanMsg])
          │
          │  response: tool_call(lookup_application, {"app_id": "APP-009"})
          ▼
    tools_node → lookup_application.invoke({"app_id": "APP-009"})
          │
          │  returns: {id: APP-009, state: TX, coverage: 1200000, ...}
          ▼
    agent_node → ChatAnthropic.invoke([..., ToolMessage])
          │
          │  response: tool_call(retrieve_rules, {"risk_factor": "coverage"})
          ▼
    tools_node → retrieve_rules.invoke({"risk_factor": "coverage"})
          │
          │  returns: ["Coverage > $1M requires mandatory refer. Flag: high_coverage"]
          ▼
    agent_node → ChatAnthropic.invoke([..., ToolMessage])
          │
          │  response: tool_call(draft_decision, {decision: "refer", ...})
          ▼
    tools_node → draft_decision.invoke({...})
          │
          │  updates state: {decision: "refer", flags: ["high_coverage"], ...}
          ▼
    should_continue → END (no more tool calls)
          │
          ▼
    Loop 2: decision == "refer" → write human_queue.json → return (state, True)
          │
          ▼
    Loop 3: passed=True → update run_state.json → remove APP-009 from queue
          │
          │  [decisions_since_last_improvement becomes 9 >= 8]
          ▼
    Loop 4: improve(seed_prompt, lessons, meter, rounds=5)
          │
          │  reflect → evaluate → audit → gate → write best_prompt.txt
          ▼
    Loop 3: continue with APP-010 using new best_prompt

Ключовыя урокі інжынерыі

Этап «Ключовыя інжынярскія урокі» працюе наўздычай, калі яго розглядаць як вимерную паверхню. Запісаўце адна «золатая» транскрыпцыя, адзін прыклад неудачы і прыметку па адвярненню роботы перш чым расширваць масштаб. Волійце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выходзіць, прычына неудачы павінна вказваць на адную адпаведальнасць, а не на заплутаны ланцюг задач. Рэзервавайце стан графа як просты і з адзінаковым типам дадзеных. Вярсткаваныя блакі маскуюць, який вузол запісаў канкрэтны поле, і спакойваюць працу пасля перарываў.

1. Раздзеліце оракула ад агента

Этап «1. Раз’ядраць стадію Oracle» працюе найэфектывней, калі яго спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адны прыклад неудачі і запіс пра відкатанне раней, чым расширваце сферу дзеяння. Спрыявайце гэты стадію як кантракт межаў між вхіднымі даннымі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, задаце критэрыя успеху і не падзеўляйцеся частым, непূরным выкананнем задач. Храніце стан графа ў простам і типаваным формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакшваюць продажчыку роботу пасля перарываў. Этап «1. Раз’ядраць стадію Oracle» працюе найэфектывней, калі яго спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адны прыклад неудачі і запіс пра відкатанне раней, чым расширваце сферу дзеяння. Храніце настройкі за межама коду прыемлівача. Файлы сераў, хранальнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куды аператары можаць аудытаваць іх, не чытаючы весь граф.

2. Дэтэрмінізм на межы ацэнкі

Для параграфа «2. Дэтэрмінізм на даным этапе» неабяжна практычна апранаванне: перад змінайом код неабяжна задаць вхідныя даны, абонента крока і критэрыі завершэння. Аператары должны магчымаць перапрацоўкі крока з вядомага пункта контролю без неабяжнай адгадванняя схованага стану. Неабяжна задокументаваць як «шчаслівы» шлях, так і шлях вяснавання. Перапрацоўкі, людзкія перакрыцця і обробка некоректных паведамленняў є часткай продукту, а не яго пазнейшай дапрацоўкі. Неабяжна прысваяць людзкую згоду там, дзе відбываецца выдатак грошэй або зміняюцыся даны для працы. Компіляцыйныя налашчэнні не є адпаведнікамі пачатковай готовасці продукту.

3. Інструмент draft_decision як структураваная экстракцыя

У стадії 3 – інструменту праграматы рашэння – перад тым, як зменшыць код, неабяжна визначыць данні, адпаведальную особу за крок і критэрыі завершэння. Аперацыяныя працавнікі должны магчымаць перзапуск крока з вядомай точкі контролю, не падозрываючы прыхованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі крок не выйшаў, прычына нехасабності должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцужок задач. Автентыфікуйцеся на входзе і паўторна автарызуйцеся на роўні дадзенняў. Толькі токэн-носіцель не є межай адпаведальнасці.

4. Борьба з чырваннем ў самапраўляючыхся системах яе неабходна

Для 4-го этапу протырання, які ўсуненне шахрайства на яком не ёсць неабяжным, перад зменой коду трэба вызначыць вхідныя даны, адпаведальнага за этап і крэтыры завершэння. Аператары должны магчымаць перзапуск этапа з вядомай точкі контролю без адгадвання захаванага стану. Спрыяйце цэму этапу як кантракту межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, вызначыце перакананні успеху і адмовіцеся ад тыхняга частковага завершэння без паведамлення. Забезпечыце людскія апраўленні для тых ситуацый, дзе витрачаюцца грошы або зміняюцыся даны для працы. Компіляцыйныя налашчэння не ўзроўнаўцуюцца з павнай завершанасцю бізнес-процэсаў. Для 4-го этапу протырання, які ўсуненне шахрайства на яком не ёсць неабяжным, перад зменой коду трэба вызначыць вхідныя даны, адпаведальнага за этап і крэтыры завершэння. Аператары должны магчымаць перзапуск этапа з вядомай точкі контролю без адгадвання захаванага стану. Зберагачыце налашчэнні параду працоўным кодам програмы. Файлы сераўіса, хранільнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнай чытання.

весь граф.

5. BOM і кодаванне — это багі ў працэспрыёмнасці

Калі працюеце над этапамі BOM і кодавання, спачатку запісайце умовы: неабяжлівыя данні, сигнал успеху і тое, што выходзіць у разе частковага невыпання. Такі список контроля дапамагае заліцвачыць змяны ў кодзе чыста. Документавайце як шлях успеху, так і шлях вярнення да нормы. Перапрыбуткі, людзкі контроль і обработка некоректных паведамленняў є частью продукту, а не дадатковымі правкамі. Стварайце контрольныя пункты пасля дорогіх крокаў. Система вярнення не павінна занова ставіць плату за той самы вызов LLM, калі аператар перапрыбуе пазнейшы вузел.

6. Бюджет — апераду, а не пасля расходаў

Калі працюеце на стадыі «6. Бюджет перад выкананнем», спачатку запісайце умовы контракту: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконтроўкі дапамагае заліцвачыць змяны ў кодзе. Валіце маленькія, тэставаныя елементы замест вялікіх скрыптав. Калі якісь крок не выйшае, прычына нявыпання павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Зробіце пераконтроўку пасля дорогіх крокаў. Програма не павінна знову выкананыць той самы вызов LLM, калі аператар пракушае выкананне наступнага элемента.

# WRONG: allows one overspend before raising
self.spent += cost
if self.spent > self._budget:
    raise BudgetExhaustedError(...)
# CORRECT: raises before the overspend registers
if self.spent >= self._budget:
    raise BudgetExhaustedError(...)
self.spent += cost

7. flush=True у лініях прыступу ў дугах, якія выкананыя дзеўальна

Калі працуеце над практыкай «7 flush True» на данай стадыі, спачатку запісаце кантракт: неабяжлівыя вхідныя даны, сигнал працэздольнасці і тое, што выходзіць на частковай нявыполненасці. Такі чэк-ліст дапамагае заставіць пазнейшыя змены коду быць чыстымі. Спрэтавайцеся да гэтай стадыі як да кантракта межаў вхідных дадзеных і перакананых выходных рэзультатаў. Даць назвы артыфактам, задаць правіла пераканання пра працэздольнасць і не падтрымляць тыхя частковых завершэнняў, якія не фіксуюцца. Ствараце контрольныя пункты пасля дорогіх крокаў. Система вярнення не должна зноў выклікаць той самы калект працэздольнасці LLM, калі аператар праказвае спробу на пазнейшым вузле.

print(f"[loop3] {processed}/{total}  {app_id} ...", flush=True)

Калі працуеце над практыкай «7 flush True» на данай стадыі, спачатку запісаце кантракт: неабяжлівыя вхідныя даны, сигнал працэздольнасці і тое, што выходзіць на частковай нявыполненасці. Такі чэк-ліст дапамагае заставіць пазнейшыя змены коду быць чыстымі. Зберагаце настройкі за межамі коду прыемлівача. Файлы сераўнавання, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжлівага чытання всей структуры.

8. Бюджет для алгорытму падыбання ў гары должен быть аддзельным ад бюджету ціклу захода

Бюджет для алгорытму падыбання ў гары краща функцыонуе, калі яго розглядаюць як вимерную паверхню. Перш чым расширваць масштаб, зафіксавайце адны ідеальны прыклад роботы, адзін прыклад неудачы і прыметку па вярнэнню да поперадньего стану. Запісуйце адночасна шлях успеху і шлях вярнэння. Перапрыбуткі, людзкі контроль і обработка некоректных паведамленняў є частью продукту, а не етапамі далейшай наладкі. Храніце стан графа у простаму і типаванаму формате. Вкладаныя структуры маскуюць інфармацію пра тое, який вузел запісаў кожна поль і спакоююць працу пасля перерываў.

try:
    system_prompt = run_hill_climbing(system_prompt, lessons, meter)
    run_state["decisions_since_last_improvement"] = 0
except BudgetExhaustedError:
    print(f"[loop3] hill-climbing skipped — budget exhausted at ${meter.spent:.4f}")
    run_state["decisions_since_last_improvement"] = 0

Розшырэнне гэтага шаблона

Этап расшырэння гэтага шаблона працюе найкраща, калі яго расследжваць як меравальную паверхню. Зафіксавайце адны ідеальны прыклад, адну справу з бягам і прыметку пра вярнэнне да пачатковага стану перш чым расширваць масштаб. Валіце маленькія, тэставальныя элементы замест большых скрыптов. Калі якісь крок збягае, прычына бягу должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Рэзервавайце стан графа ў простам і типізаваным формате. Вярнутыя структуры маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакойваюць працу пасля перерываў.

Запуск системы

Этап «Адміністрацыя системы» працюе наўздоўж краща, калі яго спрыягчваць як мерыемую паверхню. Зафіксуйце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярненне да пачатковага стану перш чым расширваць сферу дзеяння. Спрыягчвайце этап як кантракт межа вхіднымі даннымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаць критэрыя успеху і адмовіцеся ад тыхнай частковай рэалізацыі, якая не зафіксавана. Зберагачыце стан графа ў простам і типаванам формате. Вкладзеныя блокі маскуюць інфармацыю пра тое, який вузел запісаў кожны поле, і спакоююць продажчыку роботы пасля перарываў.

# 1. Install
cd underwriting_loop
pip install -e ".[dev]"
export ANTHROPIC_API_KEY=sk-ant-...
# 2. Run a single application (debug mode - cheapest)
python -m src.main --mode single --app-id APP-001
# 3. Drain the pending queue with event loop
python -m src.main --mode event-loop --once
# 4. Run standalone hill-climbing (5 rounds)
python -m src.main --mode improve --rounds 5
# 5. Run the full offline test suite (no API key needed)
pytest tests/ -v

Этап «Адміністрацыя системы» працюе наўздоўж краща, калі яго спрыягчваць як мерыемую паверхню. Зафіксуйце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярненне да пачатковага стану перш чым расширваць сферу дзеяння. Зберагачыце настройкі параду з кодам прыемлівача. Файлы сераўнавальнага сераўсу, хранілішчы секрэтных данных і флагі функцый должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабходнасці чытання всего графа.

seed score: 44%  (9 failures)
round 1: 56% KEPT  (7 failures)
round 2: 56% REVERTED (score 56% <= best 56%)
round 3: 69% KEPT  (5 failures)
round 4: 75% KEPT  (4 failures)
round 5: 69% REVERTED (score 69% <= best 75%)
Final test evaluation...
spend:              $1.8342
test score:         75%
gain (vs baseline): +25%

Вывык

У стадії заканчэння неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і критэрыя завершэння пры зміне коду. Аперацыйныя працавнікі должны магчыма ўвайсці крок з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Неабяжна задокументаваць як шлях успеху, так і шлях вярнення. Перапрыбуткі, людзкіе перакрыцця і обробка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней. Неабяжна застосавіць людзкую апраўдку для тых крокаў, якіе выкарыстоўваюць грошы або зміняюць даны ў працэсе виробніцтва. Праця ў часе компілявання не абавязкова значыць повноту бізнес-функцый.

Працоўныя і недзеянкі інжынерыі циклаў

Ёнколі хацецца аналізаваць прынтэсы і недакладнасці стадзій, пярш чым зменаваць код, неабходна ўзначыць вхідныя даны, адпаведальнага за стадзію і крэтыры завершэння. Аперацыяныя працавнікі павінны магчымае перадзеяць стадзію з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Лепш выбіраць маленькія, тэставаныя елементы замест большых скрыптов. Калі стадзія не выйшла, прычына нехацякавага рэзультата павінна вказываць на аднойчыную адпаведальнасць, а не на заплутаную схему выконання задач. Неабходна людская апрацоўка там, дзе выконваюцца грошовыя расходы або зміняюцыся даны для працы системы. Компіляцыйныя налашчэння не ўзначаюць павнае выпаненне бізнес-процэса.

Прынтэсы

Для стадіі Pros неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры змены коду. Аперацыйныя працавнікі должны магчымае перайсці караць крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Спрацавляйце гэтую стадію як кантракт межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, узначыце перакананні пра успех і адмовіцеся ад тыхняй частковай завершэнні без паведамлення. Заставьце людзкую апраўду на тых элементах, якія выкарыстоўваюць грошы або зміняюць даны для працы. Компіляцыйныя налашчэння не ўзначаюць павнае выпаненне задачі. Для стадіі Pros неабяжна ўзначыць вхідныя даны, адпаведальнага за крок і крэтырыя завершэння пры змены коду. Аперацыйныя працавнікі должны магчымае перайсці караць крок з вядомага пункта контролю, не спрабоўваючы здагадвацца пра схованы стан. Зберагайце налашчэнні параду коду прыкладнення. Файлы сераўіса, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, якое працавнікі можу аудытаваць, не чытаючы весь ланцуг.

Недакладнасці

Калі працуеце над стадзіяй Cons, спачатку запісайце контракт: неабяжлівыя даны, сігнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконтроўкі дапамагае заліцварыць пазнейшыя змены ў кодзе. Документавайце як шлях успеху, так і шлях вяснавання. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў ёсць часткаю продукту, а не пазнейшым дапрацоўкам. Зробіце пераконтроль пасля дорогіх крокаў. Система вяснавання не должна зноў вырахоўваць плата за той самы вызов LLM, калі аператар перапрыбуе пазнейшы вузел.

Калі выкарыстоўваць інжынерыю циклаў — і калі не выкарыстоўваць

Калі працюеце над этапам «Калі викорыстоўваць цыкл», спачатку запісайце умовы ўгоды: неабходныя даны, сігнал успеху і тое, што выходзіць пад час частковага невыпання. Такі список пераконтрацый дапамагае залічыцца з пазнейшымі змянамі ў кодзе. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшоў, невыпанне должна паказваць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Зробіце пераконтрацыю пасля дорогіх крокаў. Програма не должна зноў ставіць плату за той самы вызов LLM, калі аператар праканае пазнейшы вузел.

Тэст з двумя запытаннямі

Калі працюеце над стадзіяй «Тэст з двума запытаннямі», спачатку запісайце контракт: неабяжныя вхідныя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список перакладоў заходзіць пазнейшыя змены коду чыстымі. Спрыятлівае ставленне да гэтай стадзіі як да контракту межа вхіднымі данымі і перакананымі выходнымі рэзультатамі. Дайце назвы артыфактам, задаце правіла пераканання успеху і адмовіцеся ад мовчкавага частковага завершэння. Зробіце перакананне пасля дорогіх крокаў. Програма не должна зноў выклікаць той самы календар LLM, калі аператар прабуе зноў запрацаваць з пазнейшым вузлам. Калі працюеце над стадзіяй «Тэст з двума запытаннямі», спачатку запісайце контракт: неабяжныя вхідныя даны, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список перакладоў заходзіць пазнейшыя змены коду чыстымі. Зберагаце настройкі праза код аплікацыі. Файлы сераў, хранільнікі секрэтных дадзеных і флагі функций должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнага чытання всіх элементаў.

Калі вжываць інжынерыю циклаў

Інжынерыя ціклоў працюе найэфектывней, калі етап розглядаецца як вимерная паверхня. Зафіксавайце адны ідеальны прыклад роботы, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштабы. Документавайце як шлях успеху, так і шлях вяснавання проблемы. Перапрыбуткі, людзкія контрольныя пункты і обработка некоректных паведамленняў є частью продукту, а не етапамі далейшай доработкі. Храніце стан графаў у простам і типаваным формате. Вкладзеныя структуры маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакоююць працу пасля перарываў.

Не вжывайце інжынерыю ціклоў, калі

Этап «Не вяроць у цікл» працюе найэфектыўней, калі яго розглядаць як мерыемую паверхню. Зафіксавайце адна ідеальная транскрыпцыя, адзін прыклад неудачы і запіс пра вярнэнне да пачатковага стану, перш чым расширваць масштаб. Валіце малыя, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына неудачы павінна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Рэзервавайце стан графа ў простам і типізаваным формате. Вярнутыя структуры маскуюць інфармацыю пра тое, який вузел запісаў канкрэтны поле, і спакойваюць працу пасля перарываў.

8 аспектаў, якія робяць цікл практычна працэздатным

8 прычын, чырвоныя якія робяць стадію кращай, калі яе спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адны прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштаб. Спрыявайце гэтую стадію як кантракт межа вхіднымі даннымі і перакананымі выходнымі рэзультатамі. Даўце назвы артыфактам, задаць критэрыя успеху і адмовіцеся ад тыхняй частковай роботы без паведамлення. Храніце стан графа ў простым і типаванам формате. Вярнутыя структуры маскуюць, який вузел запісаў канкрэтны поле, і спакшваюць продажчыку роботу пасля перарываў. 8 прычын, чырвоныя якія робяць стадію кращай, калі яе спрыяваць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адны прыклад неудачы і запіс пра вярнэнне да пачатковага стану перш чым расширваць масштаб. Храніце настройкі за межамі коду прыемлівача. Файлы сяродавішча, хранальнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнага чытання всего графа.

1. Пераканальная мета

Для стадіі 1 «Перапрацоўванне меты» неабходна пазначыць вхідныя даны, адпаведальнага за крок і критэрыя завершэння прычыні перад зменым коду. Аператары должны магчымае перадзягнуць крок з вядомай точкі контролю, не спрабоўваючы здогадвацца пра схованы стан. Неабходна задокументаваць як шлях успеху, так і шлях вярнення да нормальнага стану. Перапрыбуткі, людзкія пераказы і обробка некоректных паведамленняў є часткай продукту, а не елементамі пазнейшага дапрацоўвання. Неабходна людзкая затверджэнне для тых крокоў, якія выкарыстоўваюць грошы або зміняюць даны прадукцыі. Працэс складання коду не є адпаведнікам повнай бізнес-готовасці.

2. Абсалютная зупінка

Для стадіі 2 «Абсалютныя адстаўкі» неабходна пазначыць вхідныя даны, адпаведальнага за крок і крэтыяры завершэння пры перадзеі коду. Аперацыйныя працавнікі должны магчымае перадзеі крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Валіць кращэ маленькія, тэставаныя елементы за велікія скрыпты. Калі крок не выйшоў, прычына неудачы должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны процес. Неабходна людская апраўда для тых крокаў, якія выкарыстоўваюць грошы чы зміняюць даны прадукцыі. Працэс кампайлявання не є гарантыяй полнага адпрацоўвання бізнес-процэсаў.

3. Хорашыя інструменты

Для стадіі «3 Якісныя інструменты» неабходна практычная дэфініцыя вхідных даных, адпаведальнага за крок і крэтарыяў завершэння працы перад зменым коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Спрыяйце цій стадіі як даговору межы вхідных даных і перакананых выходных рэзультатаў. Даўце назвы артыфактам, практычная дэфініцыя крэтараў успеху і адмовіцеся ад беззвучнага частковага завершэння. Аутентыфікуйцеся на в’язку і паўтарна автарызуйцеся на роўні дадзенняў. Толькі токэн-носіцель не ёстся межай аренды. Для стадіі «3 Якісныя інструменты» неабходна практычная дэфініцыя вхідных даных, адпаведальнага за крок і крэтарыяў завершэння працы перад зменым коду. Аператары должны магчымаць перзапуск кроку з вядомай точкі контролю, не спрабоўваючы здагадвацца пра схованы стан. Зберагачыце канфігурацыю парад у коде прыкладнення. Файлы сяродавішча, хранільнікі секрэтных дадзенняў і флагі функцияў должны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабходнасці чытання всей структуры.

4. Памяць

Калі працуеце з 4 стадзямі памяці, спачатку запісайце угоду: неабяжлівыя даны, сигнал успеху і тое, што выходзіць у разе частковага неяксамоства. Такі список пераконтролюе чыстасць пазнейшых змян у кодзе. Дакументавайце як шлях успеху, так і шлях вяснавання. Перапрыбуткі, людзкія контралісты і обработка некоректных паведамленняў ёсцю частью продукту, а не пазнейшым дапрацоўкам. Зрабіце контрольную пазнаку пасля дорогіх крокаў. Продовжэнне работы не павінна зноў выклікаць той самы вызов LLM, калі аператар перапрыбуе пазнейшы вузел.

5. Адзінэчны пераконтролюець

Калі працуеце з этапам 5 A Separate Checker, спачатку запісайце умовы контракту: неабяжлівыя даны, сигнал успеху і тое, што выходзіць пад частковыя неудачы. Такі список пераканаець у тым, што пазнейшыя змены коду будуць чыстымі. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, неудача должна вказваць на адну адпаведальнасць, а не на заплутаны ланцюг задач. Зробіце перапактаванне пасля дорогіх крокаў. Програма не должна зноў ставіць плату за той самы вызов LLM, калі аператар праказвае пазнейшы вузел.

6. Планаваце пры выконанні складных задач

Калі працуеце за 6-ю стадзіяй «Планаванне пры дзеянні», спачатку запісайце контракт: неабяжлівыя данні, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Спрэтавайцеся да гэтай стадзіяй як да контракту межа даннімі і перакананымі выходамі. Дайце назву артыфактам, задаце критэрыя успеху і не падзволяйце частковаму завершэнню без паведамлення. Зробіце перапытку пасля дорогіх крокаў. Система вярнення не павінна зноў выкарыстоваць той самы вызов LLM, калі аператар праканае пазнейшы вузел. Калі працуеце за 6-ю стадзіяй «Планаванне пры дзеянні», спачатку запісайце контракт: неабяжлівыя данні, сигнал успеху і тое, што выходзіць у разе частковага нявыпання. Такі список пераконвае ў тым, што пазнейшыя змены коду будуць чыстымі. Зберагаўце настройкі паза кодам прыемлівача. Файлы сераўнавання, хранільнікі секрэтных дадзеных і флагі функций павінны знаходзіцца ў адном месцы, якое аператары можаць пераглядаць без неабяжлівага чытання всей структуры.

7. Логаванне

Этап 7 «Логаванне» працюе найкраща, калі яго розглядаць як вимерную плошчу. Зафіксавайце адны ідеальны прымер, адну справу з бягамі і запіс пра выканэнне атрыбута rollback перад расшырэнням масштаба. Дакументавайце як шлях успеху, так і шлях вярнення ў нормальны стан. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.

8. Розумэнне костаў

Этап 8 «Розумэнне костаў» працюе найкраща, калі яго розглядаць як вимерную плошчу. Зафіксавайце адны ідеальны прымер, адну справу з бягамі і запіс пра выканэнне атрыбута rollback перад расшырэнням масштаба. Валіце маленькія, тэставаныя елементы замест большых скрыптов. Калі якісь крок не выйшае, прычына бягу должна вказываць на адну конкрэтную адпаведальнасць, а не на заплутаны ланцюг задач. Дакументавайце як шлях успеху, так і шлях вярнення ў нормальны стан. Перапрыбуткі, людзкія контралі і обработка некоректных паведамленняў є часткай продукту, а не чымсь, што дадаецца пазней.

# The ordering matters:
if self.spent >= self._budget:          # check BEFORE adding
    raise BudgetExhaustedError(...)
self.spent += cost                       # add AFTER the check clears

Спісак перагляду

Этап Спісак перагляду працюе найэфектывней, калі яго розглядаць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адзін кейс неудачы і прыметку па вярнэнню да пачатковага стану, перш чым расширваць масштабы. Разглядзіце гэты этап як кантракт межа вхіднымі даннымі і пераканаленымі выходнымі рэзультатамі. Даўце назвы артыфактам, задаце критэрыя успеху і адмовіцеся ад тых падзеяў, калі робота завершаецца часткова без паведамлення. Храніце стан графа ў простым і типаванам формате. Вярнутыя структуры данных маскуюць інфармацыю пра тое, який вузел запісаў кожны поле, і спакойваюць продажчую роботу пасля перарываў. Этап Спісак перагляду працюе найэфектывней, калі яго розглядаць як мерыемую паверхню. Зберагчыце адны ідеальны прыклад роботы, адзін кейс неудачы і прыметку па вярнэнню да пачатковага стану, перш чым расширваць масштабы. Храніце настройкі параду з кодам прыемлівача. Файлы сяродавішча, хранальнікі секрэтных данных і флагі функцыйяў должны знаходзіцца ў аднам месцы, куда аператары можу аудытаваць іх без неабходнасці чытаць весь граф.

Справакі:

У стадії «Апавяранні» неабходна дэфініцыя вхідных даных, адміністратара крока і крэтэрыяў завершэння пры зміне коду. Аперацыйныя працавнікі павінны магчымае перадзванаць крок з вядомай точкі контролю, не падозрываючы прыхованы стан. Неабходна аддокументавацыя як «шчаслівага» шляху, так і шляху вярнення. Перапрыбуткі, людзкія пераказы і обробка некоректных паведамленняў ёсць часткай продукту, а не пасляднім дапрацоўкам. Пры выкарыстоўванні грошэй чы зміне дадзеных у працоўным режыме неабходна людзкая затверджэння. Працэс складання коду не ўзроўнюецца з повнасцю бізнес-функцыяў.

Чэк-ліст для аперацый

Працюючы над чэк-лістам для аперацый, спачатку запісуйце умовы: неабходныя вхідные даны, сігнал успеху і тое, што выканаецца у разы частковага абяўлення. Такі чэк-ліст дапамагае заставаць пасляднія змены коду чыстымі.

Запісвайце часы выконання аперацый і косць токена чыста запиту праз функцыйнальныя рэзультаты. Відразлівая візуальна інформацыя пра косць з’являецца рана, што запобегае неспакоўным счыткам, калі траекторыя пераходзіць з дэмавайнага режыма ў спакульную среду.

Ствараце контрольныя пункты пасля дорогіх крокаў. Функцыя продакцыйнага запуску не павінна зноў нарахоўваць косць той самай вызову LLM, калі аператар перапрыяўляе выконанне на пазнейшы вузел.

Зафіксавайце версіі залежнасцей і запісвайце хэш адпаведнага зображэння, якое выкорыстоўвалася для дэмавайнага тесту. Возможнасць перадзвічання рэзультатаў важлівей, чым традыцыйныя знання.

Зберагаўце настройкі праза код аплікацыі. Файлы среды, хранільнікі секрэтных дадзеных і флагі функций павінны знаходзіцца ў аднам месцы, якое аператары можаць пераглядаць без неабяжнага чытання всей структуры.

Ствараце контрольныя пункты пасля дорогіх крокаў. Функцыя продакцыйнага запуску не павінна зноў нарахоўваць косць той самай вызову LLM, калі аператар перапрыяўляе выконанне на пазнейшы вузел.

Перш чым запускать даную структуру, заморозьце версіі, зафіксавце «золаты» транскрыпты для критичных етапаў і паказвце спосабы вярнення да пачатковага стану. У спільных середавішчах неабходны ліміты швайнаў, перакананні ў належнасці тэрыторіі і чысткі власнік для змены секрэтных даных. Валіце надзейнасць працы над красавімі разовымі дэманстрацыямі.

Прыметкі для c0f4a1437d4f: не кладзіце ключы прадаўцаў у репазітарый, задаце верхнюю межу токенав на сесію і зберагачыце транскрыпты празаўседы ў фіксаты eval, каб пазнейшыя замены модэляў заставаліся пораўнанымі.