Orchestra molte sessioni Devin con uno script Python deterministico: distribuisci il lavoro, inoltra risultati strutturati tra le fasi e riprendi un run dal punto in cui si era interrotto.
I flussi di lavoro dinamici sono disponibili in qualsiasi sessione Devin: descrivi il lavoro e chiedi a Devin di eseguirlo come flusso di lavoro.
Un flusso di lavoro dinamico è uno script Python deterministico che orchestra un team di agenti Devin. Devin scrive ed esegue lo script, che decide quali agenti eseguire, in quale ordine e quali istruzioni fornire a ciascuno, utilizzando i risultati strutturati degli agenti precedenti per creare i prompt di quelli successivi.Ogni chiamata a un agente viene registrata, pertanto un run del flusso di lavoro è osservabile durante l’esecuzione e può essere ripreso in caso di interruzione: gli agenti che hanno completato il lavoro riproducono istantaneamente i risultati registrati e viene rieseguito solo il lavoro incompleto.Questo va oltre i managed Devins, in cui la sessione di coordinamento genera e supervisiona manualmente le sessioni figlie. In un flusso di lavoro, l’orchestrazione stessa è codice.
Richiedi un flusso di lavoro quando l’attività presenta una struttura ben definita:
Ampia ramificazione con un passaggio di consolidamento — circa cinque o più unità indipendenti (file, moduli, endpoint, ticket), ciascuna delle quali richiede valutazione o verifica, i cui risultati vengono poi aggregati.
Una pipeline a fasi — le fasi successive utilizzano l’output strutturato di quelle precedenti, ad esempio audit → soluzione → verifica.
Usa invece una normale sessione (o un paio di managed Devins) quando:
La modifica è meccanica — un codemod, l’autocorrezione del linter o un generatore la eseguono più rapidamente e in modo più affidabile degli agenti.
Sono necessarie solo una o due sessioni indipendenti, senza scambio di dati tra loro.
Il lavoro è strettamente interconnesso tramite uno stato condiviso, oppure è di piccola portata e sequenziale.
Descrivi l’attività e chiedi un flusso di lavoro; Devin scrive lo script.Migrazione — assegna un agente a ogni unità nel proprio branch, quindi riunisci i risultati:
Usa un flusso di lavoro per migrare ogni job in jobs/ dal runner cron legacyalla nostra nuova API dello scheduler — un agente per job, ciascuno che lavorasul proprio branch ed esegue i test del job — poi riepiloga quali jobrichiedono un intervento manuale
Ricerca — raccogli le evidenze in parallelo, quindi sintetizzale:
Usa un flusso di lavoro per valutare Postgres, DynamoDB e CockroachDB per il nuovoservizio di eventi: un agente per ciascuna opzione che la valuti rispetto ai nostri requisitidi latenza, costo e operations, poi un agente finale che confronti le evidenzee ne raccomandi una
Revisione del codice — un revisore per ogni file, quindi un passaggio di merge:
Usa un flusso di lavoro per revisionare ogni file modificato su questo branchrispetto a CONTRIBUTING.md — un revisore per file — poi unisci i risultati in ununico elenco deduplicato ordinato per gravità
Audit dell’intera codebase — una pipeline in più fasi: audit → soluzione → verifica:
Usa un flusso di lavoro per verificare ogni query SQL nel modulo di reportisticaalla ricerca di paginazione mancante e pattern N+1, risolvi ogni problema confermatosu un branch dedicato e verifica ogni soluzione con un EXPLAIN prima e dopo
Ciclo — ripeti finché una verifica non va a buon fine o i progressi si arrestano:
Usa un flusso di lavoro per far tornare verde la suite di integrazioneinstabile: eseguila, correggi tutto ciò che è fallito e ripeti finché nonpassa per tre run consecutivi o finché un ciclo non risolve nulla di nuovo
Devin scrive lo script in un file e avvia il run. Devi prima approvarlo, a meno che tu non abbia attivato l’approvazione automatica in Settings → Preferences → Auto-approve workflows.
Lo script viene eseguito sulla macchina di Devin. Le primitive del flusso di lavoro vengono iniettate automaticamente: non c’è nulla da installare o importare.
Ogni chiamata dell’agente avvia un agente e attende il relativo output strutturato. Per impostazione predefinita, tale agente è una sessione Devin indipendente sulla propria VM.
L’avanzamento viene trasmesso alla sessione. Il pannello del flusso di lavoro mostra ogni fase, i relativi agenti e il loro status in tempo reale; da lì puoi aprire la sessione di qualsiasi agente.
I risultati vengono registrati con un ID run, che consente di riprendere l’esecuzione.
Il run viene eseguito in background, quindi la sessione rimane reattiva: puoi continuare a parlare con Devin durante l’esecuzione, chiedere un riepilogo dell’avanzamento o chiedergli di interrompere il run. L’interruzione annulla lo script e mette in sleep le sessioni figlie rimanenti; tutto ciò che è già stato registrato può essere ripreso.
Lo script è semplice codice Python. Devin lo scrive, ma è utile conoscerne la struttura quando lo si esamina:
Primitiva
Funzione
register_workflow(meta)
Dichiara il nome, la descrizione e le fasi del flusso di lavoro. Deve essere atteso prima di eseguire qualsiasi agente.
agent(prompt, phase=..., schema=...)
Esegue un agente e restituisce il suo output strutturato come dict.
pipeline(items, stage1, stage2, ...)
Esegue ogni elemento nelle fasi in modo indipendente: non c’è alcuna barriera tra le fasi, quindi l’elemento A può trovarsi nella fase 3 mentre l’elemento B è ancora nella fase 1.
parallel([...])
Esegue contemporaneamente callable asincroni e attende che siano tutti completati. Usalo solo quando una fase richiede effettivamente tutti i risultati precedenti, ad esempio per un passaggio di merge o deduplicazione.
log("message")
Scrive una riga di avanzamento visibile mentre il run è ancora in esecuzione.
Ogni chiamata a agent() accetta uno schema JSON e restituisce un dict conforme a tale schema; in questo modo i risultati di una fase diventano il prompt della fase successiva. Mantieni gli schemi piccoli e semplici.
Una pipeline di audit seguita dalla risoluzione su tre moduli:
import asyncioimport jsonREPO = "github.com/acme/api"MODULES = ["auth", "billing", "search"]META = { "name": "error-handling-audit", "description": "Audit and fix error-handling bugs across api modules", "phases": [ {"title": "analyze", "detail": "audit each module for error-handling bugs"}, {"title": "fix", "detail": "fix confirmed issues and push a branch"}, ],}FINDINGS_SCHEMA = { "type": "object", "properties": { "module": {"type": "string"}, "issues": {"type": "array", "items": {"type": "string"}}, }, "required": ["module", "issues"],}FIX_SCHEMA = { "type": "object", "properties": {"branch": {"type": "string"}, "summary": {"type": "string"}}, "required": ["branch", "summary"],}async def analyze(module): return await agent( f"In {REPO}, audit the '{module}' module for error-handling bugs. " "Report each issue as a one-line string.", phase="analyze", schema=FINDINGS_SCHEMA, label=f"analyze-{module}", )async def fix(findings): if not findings["issues"]: return None return await agent( f"In {REPO}, fix these issues in the '{findings['module']}' module:\n" + json.dumps(findings["issues"], sort_keys=True) + "\nPush your work to a new git branch (do not open a PR) and " "report the branch name and a one-line summary.", phase="fix", schema=FIX_SCHEMA, label=f"fix-{findings['module']}", )async def main(): await register_workflow(META) results = await pipeline(MODULES, analyze, fix) for module, result in zip(MODULES, results): log(f"{module}: {result['branch'] if result else 'no fix needed/failed'}")asyncio.run(main())
Per impostazione predefinita, ogni agente viene eseguito sulla propria VM, ma può essere bloccato sulla macchina della sessione orchestratrice.
VM separata (predefinita)
Una sessione Devin figlia completa con macchina, cloni del repo e ambiente propri. Non può vedere i file della sessione orchestratrice, quindi il passaggio del codice avviene tramite branch Git: ogni agente esegue il push di un branch e ne comunica il nome, che le fasi successive leggono dall’output strutturato.
VM condivisa
L’agente viene eseguito sulla macchina della sessione orchestratrice e condivide il relativo albero di lavoro, incluse le modifiche non sottoposte a commit: non è necessario alcun passaggio tramite Git. Usala quando gli agenti devono leggere o modificare l’albero di lavoro corrente oppure quando il repo esiste solo su quella macchina.
Gli agenti su VM condivisa competono con la sessione per CPU, memoria e disco e sono soggetti a un limite di concorrenza inferiore. Poiché condividono un unico albero di lavoro senza isolamento, agli agenti che scrivono in parallelo devono essere assegnati file o directory rigorosamente distinti.Gli agenti possono anche essere bloccati su una modalità Devin specifica, ad esempio il più economico Devin Lite per la classificazione di singoli elementi in un’ampia distribuzione parallela.
Uno script di flusso di lavoro viene rieseguito dall’inizio quando un run viene ripreso e ogni chiamata dell’agente è associata a un hash del relativo prompt, schema e impostazioni di esecuzione. Tutto ciò che è già stato completato viene riprodotto a partire dal risultato registrato; il resto viene eseguito nuovamente in nuove sessioni.Questo funziona solo se lo script effettua ogni volta le stesse chiamate. La logica del flusso di lavoro e i prompt non devono dipendere dall’ora o dalla data corrente, dalla casualità, dagli ID generati, dalle variabili di ambiente, dallo stato del filesystem o dalle risposte di rete. Tutto ciò che richiede l’ispezione del mondo esterno deve trovarsi all’interno di una chiamata agent(), il cui output registrato viene utilizzato dal resto dello script.Due conseguenze importanti:
La modifica di un prompt riesegue quell’agente e tutti quelli successivi, mentre gli agenti precedenti non modificati vengono comunque riprodotti.
Un run scaduto per timeout o interrotto riprende dal punto in cui si era fermato quando viene ripreso con il relativo ID. Il budget predefinito e massimo per un run è di sette giorni.
Se un agente non riesce — perché la sua sessione è terminata o non ha prodotto alcun output strutturato valido — lo script decide cosa fare: saltare l’elemento, sostituire un valore predefinito, riprovare o far fallire il run. Un run ripreso ritenta gli agenti non riusciti in nuove sessioni.
Ogni agente in un flusso di lavoro corrisponde a una sessione Devin, quindi un run può consumare molte più ACU rispetto alla stessa attività eseguita in un’unica sessione. Prima di applicare un flusso di lavoro a un intero repo, eseguilo su una porzione — una directory, tre moduli o una domanda più circoscritta — e verifica l’utilizzo delle ACU degli agenti nel pannello del flusso di lavoro. Richiedere una modalità meno costosa nelle fasi ad alto volume, come la classificazione per elemento, aiuta inoltre a mantenere sostenibile un’ampia distribuzione.
Una volta che un flusso di lavoro è pronto, puoi sottoporlo a commit nel tuo repo come skill: un file workflow.py accanto a un file SKILL.md che descrive quando utilizzarlo. Devin lo individuerà e lo rieseguirà per le attività future, anziché creare un nuovo script. Chiedi a Devin di salvare un flusso di lavoro e creerà i file necessari.