diff --git a/agentscope-core/src/main/java/io/agentscope/core/agent/Agent.java b/agentscope-core/src/main/java/io/agentscope/core/agent/Agent.java index d4840bf4b..913b1b103 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/agent/Agent.java +++ b/agentscope-core/src/main/java/io/agentscope/core/agent/Agent.java @@ -16,6 +16,7 @@ package io.agentscope.core.agent; import io.agentscope.core.message.Msg; +import java.util.Map; /** * Complete agent interface combining all capabilities. @@ -63,6 +64,13 @@ default String getDescription() { return "Agent(" + getAgentId() + ") " + getName(); } + /** + * Get the agent context for passing custom data across hooks and the execution lifecycle. + * + * @return Mutable context map + */ + Map getContext(); + /** * Interrupt the current agent execution. * This method sets an interrupt flag that will be checked by the agent at appropriate diff --git a/agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java b/agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java index 96935570c..951fa5b04 100644 --- a/agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java +++ b/agentscope-core/src/main/java/io/agentscope/core/agent/AgentBase.java @@ -108,6 +108,8 @@ public abstract class AgentBase implements StateModule, Agent { private final AtomicReference interruptSource = new AtomicReference<>(InterruptSource.USER); + private final Map context; + /** * Constructor for AgentBase. * @@ -143,6 +145,8 @@ public AgentBase(String name, String description, boolean checkRunning, List(hooks != null ? hooks : List.of()); this.hooks.addAll(systemHooks); sortHooks(); + + this.context = new ConcurrentHashMap<>(); } @Override @@ -155,6 +159,11 @@ public final String getName() { return name; } + @Override + public final Map getContext() { + return context; + } + @Override public final String getDescription() { return description != null ? description : Agent.super.getDescription(); diff --git a/agentscope-core/src/test/java/io/agentscope/core/agent/AgentBaseTest.java b/agentscope-core/src/test/java/io/agentscope/core/agent/AgentBaseTest.java index b375c9d2e..089c77e63 100644 --- a/agentscope-core/src/test/java/io/agentscope/core/agent/AgentBaseTest.java +++ b/agentscope-core/src/test/java/io/agentscope/core/agent/AgentBaseTest.java @@ -308,6 +308,22 @@ void testCheckRunningEnabled_ThrowsExceptionOnConcurrentCall() throws Interrupte firstCallThread.join(2000); } + @Test + @DisplayName("Should provide a mutable context map") + void testGetContext() { + // Context should be non-null and initially empty + assertNotNull(agent.getContext(), "Context should not be null"); + assertTrue(agent.getContext().isEmpty(), "Context should be initially empty"); + + // Should support put and get + agent.getContext().put("key", "value"); + assertEquals("value", agent.getContext().get("key")); + + // Each agent instance should have its own context + TestAgent agent2 = new TestAgent("Agent2"); + assertTrue(agent2.getContext().isEmpty(), "New agent context should be empty"); + } + @Test @DisplayName("Should allow concurrent calls when checkRunning is disabled") void testCheckRunningDisabled_AllowsConcurrentCall() throws InterruptedException { diff --git a/agentscope-core/src/test/java/io/agentscope/core/hook/recorder/JsonlTraceExporterTest.java b/agentscope-core/src/test/java/io/agentscope/core/hook/recorder/JsonlTraceExporterTest.java index 68b805621..4ca601695 100644 --- a/agentscope-core/src/test/java/io/agentscope/core/hook/recorder/JsonlTraceExporterTest.java +++ b/agentscope-core/src/test/java/io/agentscope/core/hook/recorder/JsonlTraceExporterTest.java @@ -60,6 +60,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -396,6 +397,7 @@ private static Map findByEventType( private static final class TestAgent implements Agent { private final String agentId; private final String name; + private final Map context = new ConcurrentHashMap<>(); private TestAgent(String agentId, String name) { this.agentId = agentId; @@ -412,6 +414,11 @@ public String getName() { return name; } + @Override + public Map getContext() { + return context; + } + @Override public void interrupt() {}