AI Engineering Academy · leksjon

Delt minne og kommunikasjon mellom agenter

Implementer et lag for delt minne med et nøkkel-verdi-lager som agenter leser fra og skriver til, slik at de kan samarbeide asynkront uten tett kobling mellom agentene.

Leksjon 4 av 413 trinn

Delt minne og kommunikasjon mellom agenter er en gratis leksjon i AI Engineering Academy på CoddyKit. Dette er leksjon 4 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i AI Engineering Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.

Problemet med agentisolering

I et fleragentsystem kjører hver agent i sin egen kontekst og vet ikke hva andre agenter gjør eller har gjort. Hvis en researcher agent oppdager et viktig faktum, hvordan får writer agent vite om det? Hvordan vet en overvåkingsagent når coder agent støter på en feil? Uten en delt kommunikasjonsmekanisme er agentene isolerte siloer som ikke kan samarbeide effektivt.

Delt minne: Blackboard-modellen

Den klassiske løsningen for kommunikasjon mellom fleragentsystemer er blackboard-modellen: et delt datalager (blackboard) som alle agenter kan lese fra eller skrive til. Agenter legger ut funnene sine, leser andres bidrag og koordinerer seg implisitt gjennom den delte tilstanden. Denne modellen kobler agentene fra hverandre – de trenger ikke å kjenne til hverandres eksistens, bare strukturen til det delte minnet.

# Simple in-memory blackboard using a dictionary
from threading import Lock

class Blackboard:
    def __init__(self):
        self._data = {}
        self._lock = Lock()  # thread-safe for parallel agents

    def write(self, key: str, value, agent_id: str):
        with self._lock:
            self._data[key] = {'value': value, 'written_by': agent_id}
            print(f'[{agent_id}] wrote: {key}')

    def read(self, key: str):
        with self._lock:
            return self._data.get(key, {}).get('value')

    def keys(self):
        with self._lock:
            return list(self._data.keys())

blackboard = Blackboard()

Vedvarende delt minne med Redis

For fleragentsystemer i produksjon, der agenter kjører som separate prosesser eller tjenester, er ordbøker i minnet ikke tilstrekkelige. Redis er det mest populære valget for delt agentminne: Det er raskt, støtter rike datatyper (strenger, hasher, lister og sorterte mengder), har innebygd TTL for utløp og håndterer samtidige lesinger og skrivinger på en trygg måte med atomiske operasjoner.

import redis
import json

class RedisSharedMemory:
    def __init__(self, prefix='agent:'):
        self.redis = redis.Redis(host='localhost', port=6379, decode_responses=True)
        self.prefix = prefix

    def set(self, key: str, value, ttl_seconds=3600):
        full_key = self.prefix + key
        self.redis.setex(full_key, ttl_seconds, json.dumps(value))

    def get(self, key: str):
        full_key = self.prefix + key
        raw = self.redis.get(full_key)
        return json.loads(raw) if raw else None

    def append_to_list(self, key: str, item):
        full_key = self.prefix + key
        self.redis.rpush(full_key, json.dumps(item))

    def get_list(self, key: str):
        full_key = self.prefix + key
        return [json.loads(x) for x in self.redis.lrange(full_key, 0, -1)]

memory = RedisSharedMemory(prefix='research_project:')

Navneområder for delt minne

I komplekse fleragentsystemer skriver agentene mange ulike datatyper, og et flatt nøkkelnavneområde blir raskt kaotisk. Bruk hierarkiske navneområder for å organisere det delte minnet på en tydelig måte. Et vanlig mønster er project_id:agent_role:data_type, for eksempel proj_123:researcher:findings eller proj_123:coder:error_log. Da blir det enkelt å spørre etter alle data for et prosjekt eller alle utdata fra en bestemt agent.

class NamespacedMemory:
    def __init__(self, project_id: str, agent_id: str, redis_client):
        self.base = f'{project_id}:{agent_id}'
        self.redis = redis_client

    def write_finding(self, topic: str, content: str):
        key = f'{self.base}:findings:{topic}'
        self.redis.set(key, content)

    def read_all_findings(self, project_id: str):
        # Read findings from ALL agents in this project
        pattern = f'{project_id}:*:findings:*'
        keys = self.redis.keys(pattern)
        return {k: self.redis.get(k) for k in keys}

# Usage
researcher_memory = NamespacedMemory('proj_123', 'researcher', redis_client)
researcher_memory.write_finding('competitors', 'OpenAI, Anthropic, Google...')

writer_memory = NamespacedMemory('proj_123', 'writer', redis_client)
all_findings = writer_memory.read_all_findings('proj_123')

Strukturert eller ustrukturert minne

Innhold i delt minne kan være ustrukturert (rå tekstblokker som LLM-en skal lese) eller strukturert (JSON-/Python-objekter med typede felt). Strukturert minne er å foretrekke fordi det muliggjør programmatisk spørring, validering og sammenslåing. Definer alltid et skjema for det hver agent skriver til det delte minnet, dokumenter det og valider skriv mot skjemaet for å hindre at én feilaktig agent ødelegger minnelageret.

from pydantic import BaseModel
from typing import Optional, list
from datetime import datetime

class ResearchFinding(BaseModel):
    topic: str
    summary: str
    sources: list[str]
    confidence: float  # 0.0 to 1.0
    written_by: str
    timestamp: datetime

# Validated write - bad data is caught before it enters shared memory
def write_finding(memory, finding_dict: dict):
    finding = ResearchFinding(**finding_dict)  # validates on creation
    memory.set(f'findings:{finding.topic}', finding.model_dump())
    print(f'Validated finding written for topic: {finding.topic}')

Hendelsesdrevet kommunikasjon med Pub/Sub

I stedet for å spørre det delte minnet jevnlig for å se etter oppdateringer kan agenter bruke publish/subscribe (pub/sub)-kommunikasjon for å varsle andre agenter når de er ferdige med en oppgave. Agent A publiserer en hendelse («research_complete»), og Agent B, som abonnerer på denne hendelsen, våkner og starter behandlingen. Redis pub/sub og meldingskøer som RabbitMQ eller Kafka støtter dette mønsteret.

import redis

# Publisher (researcher agent)
def researcher_agent(topic, redis_client):
    findings = do_research(topic)
    redis_client.set(f'findings:{topic}', findings)
    
    # Notify all subscribers that research is done
    redis_client.publish('agent_events', f'research_complete:{topic}')
    print(f'Research complete, published event for topic: {topic}')

# Subscriber (writer agent) - runs in separate process
def writer_agent_listener(redis_client):
    pubsub = redis_client.pubsub()
    pubsub.subscribe('agent_events')
    
    for message in pubsub.listen():
        if message['type'] == 'message':
            event = message['data']
            if event.startswith('research_complete:'):
                topic = event.split(':')[1]
                findings = redis_client.get(f'findings:{topic}')
                write_draft(findings)  # start writing immediately

Delt minne i LangGraph

I LangGraph er delt minne mellom agenter selve grafens tilstandsobjekt. Hver node leser fra og skriver til den samme typede tilstandsordboken. LangGraph håndterer koordineringen av lesing og skriving automatisk. I mer komplekse scenarier kan De også injisere en ekstern minneklient (Redis, database) i hver nodefunksjon ved hjelp av avhengighetsinjeksjon.

from langgraph.graph import StateGraph
from typing import TypedDict

class SharedState(TypedDict):
    # All shared data lives here - every node can read any field
    query: str
    research_findings: str   # written by researcher, read by writer
    written_draft: str       # written by writer, read by reviewer
    review_notes: str        # written by reviewer, read by writer (loop)
    final_output: str        # written by synthesizer

# Researcher writes to 'research_findings'
def researcher(state: SharedState) -> dict:
    findings = search_and_summarize(state['query'])
    return {'research_findings': findings}  # partial state update

# Writer reads 'research_findings', writes 'written_draft'
def writer(state: SharedState) -> dict:
    draft = write_from_findings(state['research_findings'])  # reads researcher output
    return {'written_draft': draft}

Minnekonflikter og konsistens

Når flere agenter skriver til delt minne samtidig, kan det oppstå skrivekonflikter. To agenter kan overskrive hverandres arbeid eller lese foreldede data mellom en lese- og en skriveoperasjon. Dette kan håndteres med optimistisk låsing (kontroller versjonen før skriving), atomiske compare-and-swap-operasjoner i Redis eller ved å serialisere skrivinger gjennom en orkestratoragent som er den eneste som skriver til kritiske minnefelt.

# Optimistic locking with Redis
def safe_write(redis_client, key, new_value, expected_version):
    with redis_client.pipeline() as pipe:
        try:
            pipe.watch(key + ':version')  # watch for concurrent modification
            current_version = int(pipe.get(key + ':version') or 0)
            
            if current_version != expected_version:
                raise ValueError(f'Version conflict: expected {expected_version}, got {current_version}')
            
            pipe.multi()  # start transaction
            pipe.set(key, new_value)
            pipe.set(key + ':version', current_version + 1)
            pipe.execute()  # atomic commit
            print('Write successful')
        except redis.WatchError:
            print('Conflict detected, retry write')

Minne-TTL og opprydding

Delt agentminne samler seg opp over tid og kan vokse uten begrensning hvis det ikke administreres. Angi alltid levetid (TTL) for minneoppføringer, slik at de utløper automatisk. For prosjektavgrenset minne bør De rydde opp i alle oppføringer når prosjektet er fullført. Bruk TTL-verdier som samsvarer med den forventede varigheten til en arbeidsflyt: korte TTL-er (minutter) for midlertidige data og lengre TTL-er (timer til dager) for resultater som kan brukes på nytt.

def cleanup_project_memory(redis_client, project_id: str):
    pattern = f'{project_id}:*'
    keys = redis_client.keys(pattern)
    if keys:
        redis_client.delete(*keys)
        print(f'Cleaned up {len(keys)} memory entries for project {project_id}')

# Set TTL when writing
def write_with_ttl(redis_client, key, value, ttl_hours=2):
    redis_client.setex(
        key,
        ttl_hours * 3600,  # convert to seconds
        json.dumps(value)
    )

# Register cleanup callback when workflow completes
def on_workflow_complete(project_id):
    cleanup_project_memory(redis_client, project_id)
    print(f'Workflow {project_id} complete, memory cleaned up')

Minne som agenthistorikk

Delt minne kan også lagre historikken over agentenes handlinger, ikke bare resultatene deres. Ved å registrere hvilken agent som gjorde hva, når og hvorfor, opprettes et revisjonsspor som er svært verdifullt for feilsøking, for å forstå hvordan et endelig resultat ble produsert og for å gjenoppta avbrutte arbeidsflyter. Denne handlingsloggen er det minnebaserte motstykket til sporing i LangSmith.

import time
from dataclasses import dataclass

@dataclass
class AgentAction:
    agent_id: str
    action_type: str     # 'research', 'write', 'review', 'tool_call'
    input_summary: str
    output_summary: str
    timestamp: float
    success: bool

def log_action(memory, action: AgentAction):
    key = f'action_log:{action.agent_id}:{action.timestamp}'
    memory.set(key, vars(action))

# Usage in an agent
def researcher_with_logging(state, memory):
    start = time.time()
    findings = do_research(state['query'])
    log_action(memory, AgentAction(
        agent_id='researcher',
        action_type='research',
        input_summary=state['query'][:100],
        output_summary=findings[:100],
        timestamp=start,
        success=True
    ))
    return findings

Velge en minnearkitektur

Den riktige arkitekturen for delt minne avhenger av distribusjonsmodellen. For LangGraph-arbeidsflyter i én prosess er graftilstanden tilstrekkelig. For agenter i flere prosesser eller distribuerte agenter bør De bruke Redis. For langvarige prosjekter som trenger varighet på tvers av omstarter, bør De bruke en relasjonsdatabase med riktig indeksering. For hendelsesdrevet koordinering mellom tjenester bør De legge pub/sub oppå den lagringen De velger.

Kort kontroll

Test forståelsen Deres av delt minne og kommunikasjon mellom agenter fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen lærte De at blackboard-modellen bruker et delt datalager der alle agenter kan lese og skrive, noe som muliggjør implisitt koordinering uten direkte kobling mellom agenter, at Redis er det foretrukne valget for vedvarende delt minne i distribuerte multiagentsystemer, og at pub/sub muliggjør hendelsesdrevet kommunikasjon slik at agenter reagerer umiddelbart når avhengigheter er fullført. Neste gang utforsker vi løkken for kodekjøring i agentoppgaver.

Gratis å komme i gang

Lær deg Python med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Delt minne og kommunikasjon mellom agenter» gratis?

Ja – hele teksten i «Delt minne og kommunikasjon mellom agenter» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av AI Engineering Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Delt minne og kommunikasjon mellom agenter»?

Implementer et lag for delt minne med et nøkkel-verdi-lager som agenter leser fra og skriver til, slik at de kan samarbeide asynkront uten tett kobling mellom agentene. Du øver på AI Engineering Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med AI Engineering Academy?

Ingen tidligere erfaring er nødvendig. AI Engineering Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 4 av 4.

Hvor lang tid tar leksjonen «Delt minne og kommunikasjon mellom agenter»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne AI Engineering Academy-leksjonen?

Ja. Alle AI Engineering Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Hvorfor enkeltagenter møter en grense
  2. Orkestrator-undergent-mønsteret
  3. Bygge fleragentpipelines med LangGraph
  4. Delt minne og kommunikasjon mellom agenter
← Tilbake til AI Engineering Academy