agentscope-harness builds a production-grade runtime infrastructure on top of agentscope-core’s ReActAgent, through two extension channels: Hooks and Toolkits. Your entry point is one class: HarnessAgent.
A bare ReActAgent handles a single request–reason–tool–reply cycle. Harness answers a different set of questions: what happens on the next turn, what happens the next day, what happens when context overflows, what happens when state is lost, what happens when a task is too heavy. It does not replace the reasoning loop — it injects hooks at critical lifecycle points and provides a baseline set of tools, packaging the default engineering answers to these questions.
Quick Start
Add the dependency:sessionId remembers the first), and explicit conversation compaction. On first run, AGENTS.md is generated under ${cwd}/.agentscope/workspace/; subsequent runs reuse it.
agentscope-examples/agents/harness-examples/harness-quickstart/src/main/java/io/agentscope/harness/example/QuickstartExample.java
Run:
.agentscope/workspace/AGENTS.mdis auto-created — this is the source of the agent’s persona- Turn 2 “What is my name?” gets the right answer because the second
call()with the samesessionId=demo-sessionauto-restored turn 1’s state viabindRuntimeContextat the start - After a few more turns that trigger compaction (≥30 messages), you can see LLM-extracted facts in
workspace/memory/YYYY-MM-DD.md; the backgroundMemoryMaintenanceSchedulerwill continue merging these intoMEMORY.md - On the next process restart, as long as
sessionIdis unchanged, the agent still remembers everything
RuntimeContext: it is the identity carrier for the current call(). sessionId determines the storage path and log archive location; userId determines the default filesystem namespace (natural multi-tenant isolation). It is not persisted — it is only shared between hooks and tools within the current call.
Extension directions: place KNOWLEDGE.md, skills/*/SKILL.md, or subagents/*.md in the workspace to enable domain knowledge injection, skill loading, and subagent orchestration respectively. Add .toolResultEviction(ToolResultEvictionConfig.defaults()) to enable large-result offloading. Use Filesystem — Three Declarative Modes to choose between shared storage, sandbox, or local+shell for where files and commands land. For isolated execution prefer filesystem(SandboxFilesystemSpec) (see Sandbox); abstractFilesystem is only an escape hatch for self-managed stores.
Core Capabilities
Each capability answers one problem → one component:- Workspace context injection — answers where does the agent’s identity come from. Before every reasoning turn,
WorkspaceContextHookinjectsAGENTS.md,MEMORY.md, today’s memory, andKNOWLEDGE.mdinto the system prompt. The workspace is the agent’s “persona and knowledge base”. - Two-layer persistent memory — answers how do conversation facts persist across sessions.
MemoryFlushHookuses an LLM to distill conversation into a daily fact log before compaction;MemoryConsolidatorruns in the background to merge and deduplicate daily logs into the long-termMEMORY.md. Still available on next startup. - Compaction and overflow recovery — answers what to do when history gets too long.
CompactionHooksummarizes history and keeps a recent tail when message/token thresholds are exceeded; when the model actually reports a context overflow,HarnessAgentcatches the error, forces compaction, and retries automatically. - Large tool result offloading — answers what to do when a single tool call returns too much.
ToolResultEvictionHookwrites oversized results to the filesystem and keeps only a head+tail preview with a placeholder in context; the agent can re-read on demand. - Session persistence — answers how to preserve state across processes.
SessionPersistenceHookwrites agent state to the workspace bysessionId; the next call automatically resumes from where it left off. - Subagent orchestration — answers how to decompose complex tasks.
SubagentsHookinjectstask/task_outputtools; the parent agent can delegate synchronously or in the background. Subagents can be declared via workspace spec files, programmatic specs, or custom factories. - Pluggable filesystem — answers how to isolate and control the agent’s environment. All file tools go through
AbstractFilesystem. Choose from three declarative modes (local+shell, composite+store, sandbox) orabstractFilesystemfor self-managed stores. Multi-tenant / session-level isolation is handled viaRuntimeContext.userIdandIsolationScope.
RuntimeContext threads through the entire call, MemoryMaintenanceScheduler runs background merges and index maintenance, AgentTraceHook provides unified trace logging, and AgentSkillRepository auto-wires SkillBox.
How Capabilities Work Together
These capabilities collectively support three pillars of “stable continuous operation”:- Identity continuity — workspace context injection re-feeds persona and knowledge to the model each turn; two-layer persistent memory distills valuable facts from conversation back into the workspace; skill auto-loading keeps reusable capabilities tied to the workspace. The agent’s persona and knowledge do not disappear when a single call ends — they accumulate in the workspace over time.
- Bounded context — conversation compaction controls depth, tool result offloading controls width, and overflow recovery is the final safety net. Together they ensure that even in arbitrarily long sessions, the context never overwhelms the model — and if it does, recovery is seamless.
- Recoverable state — session persistence ensures a process restart can continue from where it left off; RuntimeContext threads the call’s identity (
sessionId/userId) through all hooks and tools; pluggable filesystem makes “where state actually lives” (local disk, sandbox, remote) a configuration choice.
WorkspaceManager (who reads/writes the workspace), AbstractFilesystem (where the workspace lives physically), and RuntimeContext (who is speaking in this call). Each hook does only its own job and collaborates with others through these three objects — this is how Harness assembles independent capabilities into one “stably running agent”.
How Capabilities Are Injected
HarnessAgent is a thin wrapper around Agent + StateModule, internally holding a ReActAgent delegate. All capability injection happens in HarnessAgent.Builder.build():
- Hook channel: hooks are assembled in
priorityorder and passed toReActAgent(includingSandboxLifecycleHookin sandbox mode, see Architecture) - Toolkit channel:
filesystem,memory_search,memory_get,session_searchare appended to the user’sToolkit; sandbox stores additionally addshell_execute;SubagentsHookitself registerstask/task_output - SkillBox channel:
SkillBoxis auto-constructed fromworkspace/skills/or a customAgentSkillRepository
call(), bindRuntimeContext distributes the current RuntimeContext to all hooks implementing RuntimeContextAwareHook, and restores state from Session as needed.
Detailed behavior, trigger timing, and sequence diagrams for each component are in Architecture.
Related Pages
- Architecture — component definitions, lifecycle sequence diagrams, collaboration relationships
- Workspace — workspace directory structure and context injection
- Memory — two-layer memory, compaction configuration, and full-text search
- Filesystem — three declarative modes and the
AbstractFilesystemhierarchy - Sandbox — isolated execution, sandbox state, and distributed options
- Subagent — subagent specs and orchestration
- Subagent Streaming —
stream()mode child-agent event forwarding,EventSourcefields, and multi-level nesting - Tooling — built-in tool reference
- Session — session persistence and state recovery