Memory System¶
Each agent maintains its own decentralized state, with optional shared memory.
Agent State¶
Every AgentProfile has a state field — a list of message dictionaries:
from gmas.core import AgentProfile
agent = AgentProfile(agent_id="researcher", display_name="Researcher")
# Read state (list of dicts)
current_state = agent.state # []
# Append state immutably
agent = agent.append_state({"role": "user", "content": "query"})
agent = agent.append_state({"role": "assistant", "content": "response"})
# Replace state entirely
agent = agent.with_state([{"context": "new data"}])
# Clear state
agent = agent.clear_state()
Since AgentProfile is a frozen Pydantic model, all mutations return a new instance.
Memory in Execution¶
Enable memory to have the runner automatically save and inject agent context:
from gmas.execution import MACPRunner, RunnerConfig, MemoryConfig
config = RunnerConfig(
enable_memory=True,
memory_config=MemoryConfig(
working_max_entries=10, # short-term memory limit
long_term_max_entries=50, # long-term memory limit
),
memory_context_limit=5, # include last 5 entries in prompt
)
runner = MACPRunner(llm_caller=llm_caller, config=config)
result = runner.run_round(graph)
How Memory Works¶
- Before an agent runs, the runner fetches its recent memory entries and includes them in the prompt
- After the agent responds, the response is saved to the agent's working memory
- If incoming agents shared data, their responses are also recorded
- The
memory_context_limitcontrols how many entries are injected into the prompt
Accessing Memory After Execution¶
# Get an agent's memory
memory = runner.get_agent_memory("researcher")
if memory:
print(memory.working) # working memory entries
print(memory.long_term) # long-term entries
SharedMemoryPool¶
Share data between agents through a centralized pool:
from gmas.execution import SharedMemoryPool
pool = SharedMemoryPool()
# Write data (any agent can write)
pool.write("research_findings", "Key data about quantum computing")
# Read data (any agent can read)
value = pool.read("research_findings")
# Use with runner
runner = MACPRunner(
llm_caller=llm_caller,
memory_pool=pool,
)
The shared pool is useful for:
- Sharing context that isn't passed via graph edges
- Accumulating data from multiple agents
- Providing global configuration or state to all agents
Memory + Graph Flow¶
In a typical pipeline, memory complements the graph edge communication:
researcher ──(edge)──> analyst ──(edge)──> writer
researcher writes to shared pool
analyst reads from shared pool + gets researcher's output via edge
writer reads from shared pool + gets analyst's output via edge
Edge communication passes the immediate predecessor's response. Memory provides accumulated context across the entire run.