AI Engineering Academy · Les

Statusbeheer over uitvoeringsstappen heen

Bewaar variabelen, dataframes en geïmporteerde bibliotheken over meerdere code-uitvoeringsstappen heen, zodat de agent op eerdere resultaten kan voortbouwen zonder eerdere berekeningen opnieuw uit te voeren.

Les 3 van 413 stappen

Statusbeheer over uitvoeringsstappen heen is een gratis AI Engineering Academy-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject AI Engineering Academy. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus AI Engineering Academy bevat in totaal 4 lessen.

Het probleem van statelessness

Elke uitvoering van een Docker-container start met een nieuwe Python-interpreter. Variabelen die in iteratie 1 zijn gedefinieerd, bestaan niet in iteratie 2. Deze statelessness dwingt de agent om bij elke uitvoeringsstap alles opnieuw te berekenen of opnieuw te laden — tenzij je een expliciete strategie voor statusbeheer implementeert om de status tussen iteraties te bewaren en te herstellen. Zonder zo'n strategie zijn analyses met meerdere stappen onmogelijk.

# Iteration 1 - works fine
df = pd.read_csv('data.csv')  # df is in memory
df_cleaned = df.dropna()
print('Rows after cleaning:', len(df_cleaned))

# Iteration 2 - NEW container, df_cleaned is GONE
result = df_cleaned.groupby('category').sum()  # NameError: df_cleaned is not defined
print(result)  # This will fail!

Status bewaren in bestanden

De eenvoudigste en meest draagbare aanpak is om de status in bestanden op te slaan. Aan het einde van elk codeblok slaat de agent DataFrames, woordenboeken of andere objecten op in bestanden in de werkruimtemap. De volgende iteratie laadt ze weer. Parquet is ideaal voor DataFrames, JSON voor woordenboeken en pickle voor willekeurige Python-objecten (hoewel pickle uit niet-vertrouwde code een beveiligingsrisico vormt).

import pandas as pd
import json
from pathlib import Path

WORKSPACE = Path('/workspace')

# Iteration 1: process and SAVE
df = pd.read_csv(WORKSPACE / 'raw_data.csv')
df_cleaned = df.dropna().reset_index(drop=True)
df_cleaned.to_parquet(WORKSPACE / 'cleaned.parquet')  # save for next iteration

stats = {'rows': len(df_cleaned), 'columns': list(df_cleaned.columns)}
with open(WORKSPACE / 'stats.json', 'w') as f:
    json.dump(stats, f)

print('Saved cleaned data:', len(df_cleaned), 'rows')

# Iteration 2: LOAD and continue
df_cleaned = pd.read_parquet(WORKSPACE / 'cleaned.parquet')  # restore state
with open(WORKSPACE / 'stats.json') as f:
    stats = json.load(f)
result = df_cleaned.groupby('category')['value'].sum()
print(result)

De agent leren om status in bestanden te bewaren

Je kunt status in bestanden niet alleen in je infrastructuur implementeren — de LLM moet ook op de hoogte zijn van deze afspraak en die consequent toepassen. Neem expliciete instructies op in de systeemprompt: sla een resultaat dat later nodig is altijd op met een beschrijvende bestandsnaam en laad aan het begin van elke iteratie altijd de bestanden die in eerdere stappen zijn geproduceerd voordat je verdergaat.

STATE_MANAGEMENT_INSTRUCTIONS = '''
State persistence rules:
- You have a persistent workspace at /workspace/
- After computing any result you will need later, SAVE it to /workspace/
  - DataFrames: use .to_parquet('/workspace/name.parquet')
  - Dicts/lists: use json.dump to /workspace/name.json
  - Text: write to /workspace/name.txt
- At the start of each code block, LOAD the files you need from previous steps
- Use clear, descriptive filenames like 'cleaned_data.parquet', not 'tmp1.parquet'
- When listing files, use: import os; print(os.listdir('/workspace/'))
'''

Kernelstatus met persistente Python-processen

Een alternatief voor status in bestanden is om tussen iteraties een persistent Python-proces (zoals een Jupyter-kernel) actief te houden en elk codeblok erin te injecteren met exec(). Variabelen die in de ene iteratie zijn gedefinieerd, blijven in de volgende iteratie beschikbaar. Deze aanpak is sneller en natuurlijker, maar vereist één persistent proces per agentsessie in plaats van tijdelijke containers.

import jupyter_client

class PersistentKernel:
    def __init__(self):
        km, self.kc = jupyter_client.manager.start_new_kernel(kernel_name='python3')
        self.kc.wait_for_ready(timeout=30)
        print('Kernel started')

    def execute(self, code: str, timeout=60) -> tuple[str, str]:
        msg_id = self.kc.execute(code)
        outputs, errors = [], []
        
        while True:
            msg = self.kc.get_iopub_msg(timeout=timeout)
            if msg['msg_type'] == 'stream':
                if msg['content']['name'] == 'stdout':
                    outputs.append(msg['content']['text'])
                else:
                    errors.append(msg['content']['text'])
            if msg['msg_type'] == 'status' and msg['content']['execution_state'] == 'idle':
                break
        
        return ''.join(outputs), ''.join(errors)

    def shutdown(self):
        self.kc.shutdown()

# Variables persist across execute() calls!
kernel = PersistentKernel()
kernel.execute('x = 42')  # x is now defined in kernel
output, _ = kernel.execute('print(x)')  # prints 42 - state persists!
kernel.shutdown()

Status beheren met een statusobject

Houd voor de orchestratorlaag van de agent (buiten de sandbox) een expliciet statusobject bij dat de huidige status van het werk van de agent volgt: welke bestanden zijn gemaakt, wat is berekend, bij welke stap de agent is en wat het einddoel is. Geef de LLM in elke iteratie een samenvatting van dit statusobject, zodat deze altijd weet waar de agent zich in de volledige taak bevindt.

from dataclasses import dataclass, field
from typing import Any

@dataclass
class ExecutionState:
    task: str
    iteration: int = 0
    workspace_files: list[str] = field(default_factory=list)
    computed_values: dict[str, Any] = field(default_factory=dict)
    completed_steps: list[str] = field(default_factory=list)
    last_output: str = ''

    def to_context_summary(self) -> str:
        return f'''Current task: {self.task}
Iteration: {self.iteration}
Completed steps: {', '.join(self.completed_steps) or 'None yet'}
Workspace files: {', '.join(self.workspace_files) or 'None yet'}
Key values: {self.computed_values}
Last output: {self.last_output[:500]}'''

    def after_execution(self, output: str, step_name: str):
        import os
        self.workspace_files = os.listdir('/workspace')
        self.completed_steps.append(step_name)
        self.last_output = output
        self.iteration += 1

Statuscontext in prompts injecteren

Injecteer telkens wanneer je de LLM aanroept voor het volgende codeblok de huidige statuscontext in het gebruikersbericht. Zo krijgt de LLM nauwkeurige informatie over welke bestanden beschikbaar zijn, wat al is berekend en wat nog moet gebeuren. Zonder deze context kan de LLM proberen bestanden die al bestaan opnieuw te maken of stappen overslaan die al zijn voltooid.

def build_iteration_prompt(task: str, state: ExecutionState, last_observation: str) -> str:
    return f'''ORIGINAL TASK: {task}

CURRENT STATE:
{state.to_context_summary()}

LAST EXECUTION OUTPUT:
{last_observation}

What is the next step? Write Python code to continue. 
Remember:
- Load data from workspace files if needed
- Save any results you will need in future steps
- If the task is complete, say TASK COMPLETE and summarize the result'''

# Use in the main loop
for step_num in range(max_iterations):
    context = build_iteration_prompt(task, state, last_observation)
    response = llm.complete(messages + [{'role': 'user', 'content': context}])
    code = extract_code_block(response)
    if not code:
        break  # done
    output, err = execute_in_sandbox(code)
    state.after_execution(output, step_name=f'step_{step_num}')
    last_observation = format_observation(output, err)

Grote tussenliggende gegevens verwerken

Data-analyseagents produceren vaak grote tussenliggende gegevensverzamelingen die duur zijn om bij elke iteratie opnieuw te laden. Pas lazy loading toe: laad alleen de gegevens die je voor de huidige stap nodig hebt. Gebruik kolomindelingen zoals Parquet, die efficiënt lezen van geselecteerde kolommen ondersteunen. Houd voor echt grote gegevensverzamelingen (100 MB+) een persistente kernel actief, zodat het DataFrame tussen iteraties in het geheugen blijft in plaats van telkens te worden geserialiseerd en gedeserialiseerd.

# Good: load only needed columns
df = pd.read_parquet('/workspace/full_data.parquet', columns=['date', 'revenue', 'region'])

# Bad: load everything even if you only need 2 columns
# df = pd.read_parquet('/workspace/full_data.parquet')  # loads 50 columns you don't need

# Good: filter early before loading full dataset
df = pd.read_parquet('/workspace/full_data.parquet', filters=[('region', '=', 'EMEA')])

# For very large files, tell the LLM about data shape upfront
df_info = {'shape': (1_000_000, 50), 'size_mb': 850, 'columns': [...]}
# Include df_info in state so LLM plans accordingly

Checkpoints voor langlopende taken

Implementeer voor taken die veel iteraties beslaan checkpointing: sla de volledige status van de agent (voltooide stappen, werkruimtebestanden, huidige voortgang) periodiek op in een duurzame opslag, zodat de taak na een onderbreking kan worden hervat. Dit is vooral belangrijk voor langdurige data-analysetaken die 30 minuten of langer kunnen duren en kunnen worden onderbroken door netwerkproblemen, API-fouten of herstarts van de server.

import json
import time

def checkpoint_state(state: ExecutionState, checkpoint_id: str, db):
    data = {
        'task': state.task,
        'iteration': state.iteration,
        'completed_steps': state.completed_steps,
        'workspace_files': state.workspace_files,
        'timestamp': time.time()
    }
    db.execute(
        'INSERT INTO agent_checkpoints (id, state) VALUES (?, ?) ON CONFLICT(id) DO UPDATE SET state=excluded.state',
        (checkpoint_id, json.dumps(data))
    )
    print(f'Checkpoint saved at iteration {state.iteration}')

def resume_from_checkpoint(checkpoint_id: str, db) -> ExecutionState | None:
    row = db.execute('SELECT state FROM agent_checkpoints WHERE id = ?', (checkpoint_id,)).fetchone()
    if not row:
        return None
    data = json.loads(row[0])
    state = ExecutionState(task=data['task'])
    state.iteration = data['iteration']
    state.completed_steps = data['completed_steps']
    print(f'Resumed from iteration {state.iteration}')
    return state

Status opruimen na voltooiing

In werkruimtes van agents stapelen bestanden zich op en kunnen ze na verloop van tijd groot worden. Implementeer altijd een opruimfase die wordt uitgevoerd wanneer een taak is voltooid of mislukt: verwijder tussenbestanden (cleaned.parquet, tmp_output.csv) en bewaar alleen de uiteindelijke uitvoerbestanden die voor de gebruiker van belang zijn. Stel voor cloudopslag levenscyclusbeleid in waarmee werkruimtebestanden na een bewaartermijn automatisch worden verwijderd.

import shutil
from pathlib import Path

INTERMEDIATE_PATTERNS = ['*.parquet', 'tmp_*.csv', 'step_*.json', 'debug_*.txt']
FINAL_OUTPUT_PATTERNS = ['report.pdf', 'final_*.csv', 'summary.json']

def cleanup_workspace(workspace_dir: str, keep_final=True):
    workspace = Path(workspace_dir)
    final_outputs = []
    
    if keep_final:
        for pattern in FINAL_OUTPUT_PATTERNS:
            final_outputs.extend(workspace.glob(pattern))
        # Move final outputs to output directory
        output_dir = workspace.parent / 'outputs'
        output_dir.mkdir(exist_ok=True)
        for f in final_outputs:
            shutil.move(str(f), str(output_dir / f.name))
    
    # Delete the workspace
    shutil.rmtree(workspace_dir)
    print(f'Workspace cleaned up. Kept {len(final_outputs)} output files.')
    return [str(f) for f in final_outputs]

Statusversies voor foutopsporing

Wanneer een code-agent onjuiste resultaten produceert, moet je de uitvoeringsgeschiedenis kunnen teruglopen om te vinden waar het misging. Implementeer statusversies door na elke iteratie een momentopname van de werkruimte op te slaan. Zo kun je de uitvoering van de agent opnieuw afspelen, tussenliggende statussen bekijken en de exacte iteratie identificeren waarin de fout optrad. Sla alleen het verschil op (de gewijzigde bestanden) om ruimte te besparen.

Contextvenster versus externe status

Bij het ontwerp van code-agents bestaat een fundamentele spanning tussen status opslaan in het LLM-contextvenster (direct beschikbaar maar beperkt) en in externe opslag (onbeperkt maar vereist expliciet beheer). De optimale strategie is: bewaar de gegevens van de huidige stap in de context, bewaar grote tussenresultaten in bestanden, bewaar het taakdoel en het plan op hoofdlijnen in de context en bewaar onbewerkte gegevens altijd op schijf. De LLM beheert de taak; het bestandssysteem beheert de gegevens.

Korte controle

Test je begrip van statusbeheer tussen code-uitvoeringsstappen uit deze les.

Samenvatting van de les

In deze les heb je geleerd dat status bewaren in bestanden met Parquet en JSON de meest draagbare manier is om status te delen tussen tijdelijke containeruitvoeringen; dat persistente kernels de overhead van opnieuw laden wegnemen door tussen iteraties een actief Python-proces te behouden; en dat statuscontextinjectie de LLM tijdens elke iteratie nauwkeurige kennis geeft van beschikbare bestanden en voltooide stappen. Hierna bouwen we een volledige data-analyseagent.

Gratis beginnen

Leer Python met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
30
Lessen
120

Veelgestelde vragen

Is de les “Statusbeheer over uitvoeringsstappen heen” gratis?

Ja — de volledige tekst van “Statusbeheer over uitvoeringsstappen heen” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus AI Engineering Academy wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus AI Engineering Academy bevat in totaal 4 lessen.

Wat leer ik in “Statusbeheer over uitvoeringsstappen heen”?

Bewaar variabelen, dataframes en geïmporteerde bibliotheken over meerdere code-uitvoeringsstappen heen, zodat de agent op eerdere resultaten kan voortbouwen zonder eerdere berekeningen opnieuw uit te… Je oefent met AI Engineering Academy door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met AI Engineering Academy te beginnen?

Ervaring vooraf is niet nodig. AI Engineering Academy op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.

Hoe lang duurt de les “Statusbeheer over uitvoeringsstappen heen”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over AI Engineering Academy?

Ja. Elke les over AI Engineering Academy bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. De code-uitvoeringslus
  2. Sandboxing met Docker en RestrictedPython
  3. Statusbeheer over uitvoeringsstappen heen
  4. Een data-analyseagent bouwen
← Terug naar AI Engineering Academy