OptionalAllowedTool patterns the agent may use without asking, in the harness's own pattern language
(e.g. Bash(git:*), Read, Grep). Deliberately passed through rather than normalised:
inventing an MJ-wide tool taxonomy would be a lossy translation of every harness's model, and
the patterns are the part operators actually reason about.
OptionalDisallowedTool patterns the agent must never use. Takes precedence over AllowedTools.
How much autonomy the harness gets. See the posture notes above.
What the agent is permitted to do inside its sandbox, expressed in MJ's vocabulary rather than any harness's.
Why this exists as an abstraction
Every harness has its own permission mechanism and its own spelling — Claude Code has
--permission-modewith six modes plus--allowedToolspatterns, others have none at all. Left unabstracted, permissions would be configured per-harness, and switching harnesses would silently change what an agent may do. That is the opposite of the property this whole design exists for: MJ owns authority, the harness supplies reasoning.So the posture and tool patterns are declared ONCE in agent metadata, overridable per run, and each adapter translates them into its own flags — or ignores them and reports that it cannot enforce them.
The postures
strict— nothing mutating without human approval. Honest today only where an adapter can actually intercept; where it cannot, the harness's own prompts have nowhere to go in headless mode and every tool call simply denies. That is a real, observed outcome, not a hypothetical: an agent asked to rungit statusacross repos had all 21 calls blocked and correctly stopped to ask for permission MJ had no way to grant.auto— the harness proceeds on its own for anything inside AllowedTools, and is refused anything in DisallowedTools. The workable default until HITL lands.dangerous— no gating at all. Only defensible inside a contained sandbox; the Docker provider with a real network policy is the intended pairing, not the local provider.