Skip to content

briefcase.integrations.gym

Terminal window
pip install briefcase-ai[gym]

Connects the guardrail framework to Gymnasium in both directions: a gymnasium.Env over any GuardrailEnv, and a wrapper that records RL episodes as decision records. The extra installs gymnasium>=0.29.

GuardrailGymEnv

from briefcase.integrations.gym import GuardrailGymEnv
env = GuardrailGymEnv(guardrail, tasks, injections)
obs, info = env.reset(seed=0)
obs, reward, terminated, truncated, info = env.step(0)
GuardrailGymEnv(guardrail, tasks, injections=(), reward_mode="utility",
render_mode=None)
.reset(*, seed=None, options=None) # options={"task_index": i} pins the task
.step(action) # -> obs, reward, True, False, info
.render() # "ansi" returns the explanation narrative
.close() # delegates to guardrail.close()
register_with_gymnasium(env_id="briefcase/GuardrailEval-v0", **env_kwargs) -> None

Single-step episodes: GuardrailEnv.evaluate() is side-effect free and single-shot, so step always returns terminated=True.

Action space is Discrete(1 + len(injections)). Action 0 submits the task’s clean request; action i submits injections[i - 1].inject(request).

Reward is 1.0 when the effect matches the task’s expected_effect, 0.0 otherwise. reward_mode="adversarial" inverts it, training an attacker rather than a verifier.

Observation is a fixed-shape spaces.Dict: agent, action, and resource as vocabulary indices, context as a Box from the policy space’s bounds, plus last_effect (Discrete(3)) and last_eval_time_ms.

info carries task_id, injection_id, effect, expected_effect, utility, security, reason, eval_time_ms, and the raw EvalResult.

Raises ValueError for empty tasks, an unknown reward_mode or render_mode, an out-of-range task_index, or an action outside the space; RuntimeError for step() before reset() or a second step() in one episode. The env passes gymnasium.utils.env_checker.check_env.

register_with_gymnasium holds the guardrail in the entry point’s closure rather than the registry kwargs that gymnasium.make deep-copies, so the made env drives the guardrail you registered. Nothing is registered at import time.

EpisodeCaptureWrapper, capture_episodes

import briefcase, gymnasium
from briefcase.integrations.gym import capture_episodes
briefcase.observe("rollouts.jsonl")
env = capture_episodes(gymnasium.make("CartPole-v1"))
env.reset(seed=0)
env.step(env.action_space.sample())
env.close()
EpisodeCaptureWrapper(env, *, exporter=None, async_capture=True,
capture_steps=True, max_obs_chars=1000,
max_action_chars=1000)
capture_episodes(env, *, exporter=None, **kwargs) -> EpisodeCaptureWrapper

A reset mid-episode, or close(), finalizes the open episode with completed=False. async_capture defaults to True because step capture sits on the hot path; pass False for short scripts that exit immediately after close(), or their records may not be delivered.

Record types

TypeEmittedCarries
rl.stepper stepepisode id, step index, action and observation reprs, reward, terminated, truncated, info keys, timing
rl.episodeper episodeenv id, total steps, episode return, completed

See Gymnasium for the narrative version and Guardrails for the framework being wrapped.