Konrad Kowalski (rootsher)Principal Platform & Reliability Architect011011010001001011011001011000000111000010110101

Human-in-the-loop: co gdy agent nie może kontynuować sam

data
kategoria
AI Agents
także w
Automation · Engineering Practices
czytanie
3 min / 606 słów

Do tej pory zakładaliśmy prosty scenariusz:

text
Jira task
|
v
Implementer Agent
|
v
repo
|
v
implementation
|
v
tests
|
v
PR

W praktyce agent nie zawsze będzie w stanie przejść cały flow samodzielnie.

Nie dlatego, że „nie wie, co zrobić” technicznie.

Czasem dochodzi do miejsca, w którym dalsza decyzja wymaga informacji, której nie ma w repo, RAG ani tickecie, albo decyzji, której organizacja celowo nie chce delegować modelowi.

Przykład.

Ticket mówi:

text
PAY-123

Add automatic retry for failed payment provider calls.

Acceptance criteria:
- retry transient failures
- maximum 3 attempts
- add metrics

Agent analizuje kod i dokumentację i zauważa, że obecny system traktuje timeout po wysłaniu żądania płatności jako stan niejednoznaczny.

Ponowienie requestu może potencjalnie utworzyć drugą płatność.

W takim przypadku agent nie powinien sam zdecydować:

text
"pewnie retry będzie OK"

Powinien się zatrzymać i zapytać:

Provider może przy timeout zwrócić nieznany wynik operacji, a ponowienie requestu bez idempotency key może utworzyć drugą płatność. Czy w tym tasku mamy najpierw dodać obsługę idempotency key, czy timeoutów nie obejmujemy retry?

To jest właśnie human-in-the-loop.

Agent przechodzi w stan oczekiwania

Flow zmienia się z:

text
RUNNING
|
v
DONE

na:

text
RUNNING
|
v
NEEDS_INPUT
|
v
WAITING_FOR_HUMAN
|
v
RUNNING
|
v
DONE

Przed zatrzymaniem agent zapisuje checkpoint.

Na przykład:

json
{
  "issue": "PAY-123",
  "repository": "payments-service",
  "branch": "agent/PAY-123",
  "step": "implementation",
  "status": "waiting_for_input",
  "question": "Provider może przy timeout zwrócić nieznany wynik operacji, a retry bez idempotency key może utworzyć drugą płatność. Czy najpierw dodajemy idempotency key, czy timeoutów nie obejmujemy retry?"
}

Dzięki temu po odpowiedzi człowieka nie musi zaczynać taska od początku.

Gdzie trafia pytanie

Najprostszy wariant w naszym flow to Jira.

Agent może dodać komentarz:

text
Implementer Agent needs input

Provider may return an unknown result after timeout.
Retrying without an idempotency key can create a duplicate payment.

Decision required:
1. Add idempotency support in this task.
2. Exclude timeout from retry scope.

Ticket może jednocześnie przejść do statusu:

text
Waiting for input

Inne możliwości:

  • Teams,
  • Slack,
  • pull request comment,
  • dedykowany panel do obsługi agentów,
  • approval task w pipeline.

Mechanizm jest drugorzędny.

Najważniejsze jest to, że agent generuje jawny event:

text
human input required

Jak agent wraca do pracy

Człowiek odpowiada:

text
Timeoutów nie retryujemy w tym tasku.
Retry tylko dla jawnych odpowiedzi 5xx.
Idempotency będzie osobnym taskiem.

Odpowiedź generuje kolejny event:

text
Jira comment / status change
|
v
resume trigger
|
v
agent runtime
|
v
load checkpoint
|
v
continue

Agent odzyskuje:

text
ticket
repo
branch
current step
previous decisions
human answer

i kontynuuje:

text
exclude timeout retries
|
v
implement retry for 5xx
|
v
tests
|
v
PR

Dlaczego state jest tutaj potrzebny

To właśnie jeden z najbardziej praktycznych powodów posiadania state.

Bez checkpointu po odpowiedzi człowieka agent musiałby odtworzyć wszystko:

text
pobierz Jira
|
v
clone repo
|
v
przeanalizuj kod
|
v
odtwórz poprzedni tok pracy
|
v
spróbuj zrozumieć, czego dotyczyła odpowiedź

Ze state:

text
load checkpoint
|
v
apply human decision
|
v
continue

Dlatego state nie jest tylko historią rozmowy.

To stan wykonywanego procesu.

Kiedy agent powinien pytać

Nie przy każdej niepewności.

Jeżeli agent będzie eskalował każdą drobną decyzję, automatyzacja szybko przestanie mieć sens.

Dobre kandydaty do human-in-the-loop to sytuacje, w których występuje przynajmniej jeden z tych warunków:

Brakuje decyzji biznesowej

Przykład:

text
Czy timeout powinien powodować retry,
jeżeli może wystąpić duplicate payment?

Wymagania są sprzeczne

Na przykład:

text
Acceptance criteria:
- API musi być backward compatible

Architecture note:
- usuń stare API

Agent nie powinien sam wybierać, który zapis jest ważniejszy.

Operacja ma duży blast radius

Na przykład:

text
terraform destroy
production deployment
database migration
permission escalation

Potrzebne są dodatkowe uprawnienia

Agent ma:

text
read repository
create branch
create PR

ale nagle potrzebuje:

text
production write access

To powinno wymagać jawnej decyzji.

Brakuje informacji, której nie da się odzyskać z dostępnych źródeł

Agent sprawdził:

text
ticket
repo
RAG
tools

i nadal nie ma odpowiedzi.

Dopiero wtedy eskaluje.

Clarification a approval

Warto rozdzielić dwa przypadki.

Clarification

Agent potrzebuje informacji:

text
Czy timeout wchodzi w zakres retry?

Po odpowiedzi może kontynuować.

Approval

Agent wie, co trzeba zrobić, ale organizacja wymaga zgody:

text
Plan includes a production database migration.

Approve execution?

Flow wygląda podobnie technicznie:

text
pause
|
v
human action
|
v
resume

ale semantycznie jest to coś innego.

W większej organizacji warto rozróżniać te dwa typy eventów.

Timeout i eskalacja

Co jeśli nikt nie odpowie?

Agent nie powinien wisieć bez końca.

Można zdefiniować policy:

text
WAITING_FOR_HUMAN
|
v
24h
|
v
reminder
|
v
48h
|
v
escalation
|
v
7 days
|
v
cancel task

To również może być częścią wspólnej platformy.

Repo agenta określa:

text
kiedy potrzebuję człowieka

a platforma może dostarczać:

text
pause
resume
timeout
notification
escalation

Gdzie co konfigurujemy

ElementGdzie
kiedy agent ma eskalowaćrepo agenta / workflow
checkpointruntime / state layer
treść pytaniaagent
kanał komunikacjiplatforma / integration layer
kto może odpowiedziećidentity / policy
resume triggerevent layer
timeoutworkflow / orchestration
audit odpowiedziobservability / state

Finalny flow

Nasz Implementer Agent nie wygląda już tylko tak:

text
ticket
|
v
implement
|
v
PR

Realny flow jest bliższy temu:

text
Jira ticket
|
v
Implementer Agent
|
v
repo + RAG + tools
|
v
implementation
|
v
decision missing?
|-- no
|   |
|   v
|   continue
|
`-- yes
    |
    v
    checkpoint
    |
    v
    WAITING_FOR_HUMAN
    |
    v
    Jira / Teams / Slack
    |
    v
    human response
    |
    v
    resume event
    |
    v
    load checkpoint
    |
    v
    continue
    |
    v
    tests
    |
    v
    PR

Human-in-the-loop nie oznacza więc, że agent przestaje być autonomiczny.

Oznacza, że organizacja jasno definiuje granicę:

Które decyzje agent może podejmować sam, a przy których ma się zatrzymać i poprosić człowieka o decyzję.

Materiały

do góry