Hoppa till innehåll

Ärenden och delegering

Ett ärende är den arbetsenhet som Control Center spårar. Det är medvetet en dum artefakt: en titel, en brödtext, en status, en ägare och en plats i ett träd. Det är inte det som agenterna kör mot — agentarbete lever i samtal och den strukturerade utdatan från en körning ligger i körningsloggen.

Tilldelning registrerar ägande; den startar ingenting

Avsnitt med rubriken “Tilldelning registrerar ägande; den startar ingenting”

Detta är det enskilt viktigaste att få rätt när det gäller ärenden.

Att sätta assignedAgentId skriver ett fält och publicerar en TicketAssigned domänhändelse. Den händelsen är en revisions- och aviseringssignal samt en pipelinetrigger. Tilldelning till en agent startar ingen körning. Det finns ingen ärendedispatcher som bevakar assignedAgentId och väcker den agenten.

Undantaget är ett team: när assignedTeamId är satt skickar TeamRoutingService ut teamledaren med driftsprotokollet och personallistan.

Om du vill att en specifik agent ska arbeta på ett ärende ber du den om det i ett samtal, eller så skickar ett pipelinesteg ut den, eller så delegerar en annan agent till den. Att tilldela ett ärende till en agent och vänta är det enda som aldrig kommer att ge något arbete.

Ett ärende kan vara helt lokalt eller backas av ett externt ärendehanteringssystem, och det bär båda på en och samma rad.

Speglingen — leverantör, extern nyckel, URL, titel, beskrivning, prioritet, etiketter, rå och normaliserad status, tidsstämplar — är en cache när ärendet är fjärrlagrat. Fjärrsystemet är sanningens källa där, och en uppdatering skriver om speglingen i sin helhet.

Överlägget — tilldelning, delegering, ytlänk, förälder, projekt, länkade PR:er — finns bara i Control Center. Ärendehanteringssystemet vet ingenting om det, och en uppdatering rör det aldrig.

Den uppdelningen är det som gör synkning säkert över huvud taget: en hämtning från leverantören kan vara destruktiv mot speglingen utan att någonsin förlora den orkestreringsmetadata som ligger ovanpå.

Statusarna löper backlog → open → inProgress → inReview → done, med blocked som en sidoloop och failed / cancelled som de övriga terminala tillstånden.

Övergångsgrafen upprätthålls bara på agent- och automatiseringsvägen — MCP-verktyg och avstämmare. En otillåten övergång där loggas och ignoreras, så en förvirrad agent kan inte gå ett ärende baklänges ut ur ett terminalt tillstånd.

Varje användarstyrd ändring i gränssnittet skickar force: true och kringgår grafen helt. En människa kan flytta ett ärende till vilken status som helst som väljaren listar — inklusive att återöppna ett terminalt sådant. Väljaren erbjuder inte failed; agenter sätter det via fail_ticket. Grafen är ett skyddsräcke för automatisering, inte en regel för hur arbete får fortskrida.

TicketWorkflowService äger varje mutation genom en enda flaskhals som läser in raden, säkerställer att den tillhör anroparens arbetsyta och skriver med en förväntad version, så att två samtidiga redigeringar inte kan skriva över varandra i tysthet.

Den fullständiga statustabellen, övergångarna, fältlistan och relationstyperna finns i Ärendelivscykel.

Varje ärende har en originKind. Enumen har fem värden — manual, pipelineStep, agentDelegation, externalSync, recovery — men bara två skrivs i dag: manual (standardvärdet i createTicket, även för delegerade barn) och externalSync (synkmotorn, vid en hämtning från leverantören). TicketWorkflowService.createTicket tar inget ursprungsargument, så pipelineStep, agentDelegation och recovery hamnar aldrig på en rad.

Delegering är där en agent skapar arbete åt en annan agent, och det är platsen där privilegier skulle kunna läcka, så spärrarna ligger på serversidan vid en flaskhals i stället för i promptinstruktioner.

delegate_task går genom TicketWorkflowService.delegateGuarded, som beräknar barnets djup och rot från förälderkedjan och sedan kör alla fyra DelegationGuards-kontrollerna: ett hopp som skulle överskrida ett djupstak på 3, ett hopp tillbaka till en agent som redan finns i kedjan (cykeldetektering), ett autonomitak (delegatens effektiva nivå i ytan får inte överskrida delegerarens) och en budgetram (delegering debiterar delegerarens återstående hårdstoppsbudget och kan inte skapa mer). Produktionskopplingen tillhandahåller båda resolverportarna. Autonomi och budget hoppas över när from_agent_id utelämnas (obegränsad / policyfri budget passerar också). En vägran kastas som en DelegationRefusedException vars meddelande når den delegerande agenten ordagrant — en högljudd nekning, aldrig en tyst icke-åtgärd.

delegate_ticket är den äldre, oskyddade syskonfunktionen: den anropar createTicket direkt och hoppar över alla spärrar. Föredra delegate_task.

Blanda inte ihop delegeringens djupstak (3, för delegate_task-kedjor) med den inbyggda harnessens nästningsgräns för subagenter (2). Det är olika gränser för olika mekanismer.

Relationer mellan förälder och underärende ligger i tickets.parent_ticket_id, som ägs av setParent / clearParent. De är inte rader i ticket_links, så allt som läser ett ärendes relationer måste slå samman båda källorna.

ticket_links håller de riktade kanterna mellan i övrigt orelaterade ärenden:

Länktyp Betydelse
blocks Källan blockerar målet
relatesTo De två ärendena är relaterade (symmetriskt)
duplicateOf Källan är en dubblett av målet

Ett projekt är en gruppering av ärenden inom en arbetsyta mot ett gemensamt mål. Projekt finns bara i Control Center och synkas aldrig till en extern leverantör.

Rader av typen TicketCollaborator är hur mer än en principal knyts till ett ärende, i en roll av assignee, collaborator eller reviewer. Människor och agenter är likställda rader — en principalId plus en collaboratorType — utan något sentinelvärde för “användaren” och utan någon främmande nyckel till någon av tabellerna.

Control Centers ärende är primärt. Att ta bort ett ärende är endast lokalt, så ett leverantörsstött ärende du tar bort tas inte bort i ärendehanteringssystemet och kan dyka upp igen vid nästa synkning. Medarbetare och barnärenden kaskaderar.

Adaptrarnas inloggningsuppgifter hämtas från serverns lager för inloggningsuppgifter (en Linear-nyckel eller GitHub-token som klistras in i Inställningar plockas upp vid nästa förfrågan; miljön såddar bara de lagren).

Ingen pipelinenod skapar, slutför eller avbryter ärenden — paletten har inget sådant steg och motorn anropar inte TicketWorkflowService. En pipelinetrigger kan ändå utlösas av TicketAssigned, TicketCompleted, TicketFailed eller TicketCancelled (de fyra är de ärendehändelser som EventPayloadMapper faktiskt mappar). Det finns ingen pipelineRunId-kolumn på ärendet; pipelinekopplingen ligger i agentens körningslogg.