Harness and Environment policy
Two parts of Plural shape what an Agent can do, and it helps to keep them apart:
- The Harness is how the contestant plays. It wraps the model and owns the loop that decides what to do next, along with any extra instructions, tools, and skills. It belongs to the Agent.
- The Environment is the world, the playing field. Its Apps offer the actions, the moves the Agent can make there, like
guessin Wordle. The Apps carry out those moves and return what the Agent is shown. The Environment does not wrap the model.
Think of an exam. The contestant brings their own way of working. The exam room sets the rules and can say "no phones". It can take things away from the contestant, but it never answers the questions for them.
Why it matters
An Environment often needs to limit what a Harness may do. A closed-book exam should not allow web search. A world with no internet access should not let a Harness fetch pages. Plural lets the Environment set that ceiling without taking over the Agent's loop.
When a Trial runs, the Harness runs inside the Runtime of that Task's Environment. The Environment can forbid Harness tools. For example, an Environment with network: no-network removes web search. That is a ceiling, not ownership of the loop.
Two kinds of tools
- Environment actions are run by the Environment. The Agent always receives them, and they cannot be denied.
- Harness tools, such as web search or file editing, are run by the Harness. When the Environment denies one, calling it returns an error with the reason (
{"error": "denied", "reason": ...}), and the Trial continues.
Skills and instructions stay with the Harness. Plural's native loop tells the model which tools are unavailable before the first turn, for example "web_search is unavailable because Environment network=none."
Nothing a Harness writes can add a score, a reward, or new actions to the Trial.
Built-in versus custom
Omit harness on the Agent to use native, Plural's built-in tool loop. Set it to "claude-code", "codex", or "hermes" for a vendor tool, or to an instance of your own Harness subclass when you need a custom loop:
from plural import Agent, Harness, HarnessResult class ResearchHarness(Harness): def run(self, task, agent, environment): completion = agent.complete( [{"role": "user", "content": task.instructions}], tools=environment.tools(), ) return HarnessResult(response=completion.text) harness = ResearchHarness()agent = Agent(model="openai/gpt-5.6-luna", harness=harness)Before a Trial starts, Plural records the content hash (a fingerprint) of the Harness's folder and its configuration. Every Harness receives the same Task, Agent, and Environment interface. See Harnesses.
How the Environment limits a Harness
An Environment's harness_policy sets which Harnesses may run and which capabilities they keep:
harness_policy: mode: allowlist allowed_harnesses: [native, support-loop] denied_capabilities: [web_search]In plain words, this says: "Only Plural's built-in loop and support-loop may play here, and neither may search the web."
mode: allow_all, the default, accepts any Harness.mode: allowlistaccepts only the Harnesses named inallowed_harnesses; any other is refused before the run starts. Includenativeto allow Plural's built-in loop.denied_capabilitiesremoves the listed capabilities.allowed_capabilities, when set, removes every capability not listed.
Going deeper: the exact rules
Plural starts from the capabilities the Harness declares and only ever removes some. On top of the policy above, it removes:
web_search,browser,network_fetch, andmcpwhen the Runtime's network isno-network;web_searchandbrowserwhen the network isallowlist;file_editwhen the Runtime has a read-only root.
The capabilities are shell, file_read, file_edit, code_execution, web_search, browser, network_fetch, mcp, subagents, and persistence.
Each Trial's receipt records the capabilities that were declared, granted, and denied, with the reason for each denial.
Important: Capability declarations describe the Harness; only the Runtime isolates code. Use Docker or a remote Runtime for a Harness you do not trust.