Skip to main content

Policy ABI

One fixed factory, one action method, and a bounded value surface visible to submitted code.

Program entry point​

Every Program directory must contain policy.py. The fixed entry point is policy.py:make_policy:

from evopolicygym.policy import PolicyContext, PolicyValue


class MyPolicy:
def __init__(self, context: PolicyContext):
self._seed = context.policy_seed

def act(self, observation: PolicyValue) -> PolicyValue:
return 0


def make_policy(context: PolicyContext) -> MyPolicy:
return MyPolicy(context)

make_policy(context) runs once for each Episode. The returned object must provide act(observation).

There is no Policy-visible learn(), reset(), update(), Submission, or Feedback method.

PolicyContext​

FieldMeaning
observation_spacePublic description of Policy-visible observations.
action_spacePublic description of admissible Actions.
metadataString-keyed, Case-independent Benchmark metadata.
environment_parametersPublic, Case-independent values bound to the configured Environment.
policy_seedAn unsigned 64-bit seed for this fresh Policy instance.

PolicyContext never contains Case identity, Environment seed, Host paths, file descriptors, credentials, pool identity, scores, runtime evidence, or scorer objects.

PolicyValue​

Values crossing the Policy boundary must be composed only from:

None | bool | int | float | str | bytes
| TensorValue
| list[PolicyValue]
| tuple[PolicyValue, ...]
| dict[str, PolicyValue]

The rules are strict:

  • floats must be finite;
  • integers must fit signed or unsigned 64-bit;
  • mapping keys must be exact strings;
  • containers are validated and detached recursively;
  • custom Python objects and pickle graphs are rejected.

TensorValue​

TensorValue carries a canonical dense tensor:

from evopolicygym.policy import TensorValue

pixels = TensorValue(
dtype="uint8",
shape=(84, 84, 3),
data=raw_rgb_bytes,
)

Supported dtypes are bool, unsigned and signed integers from 8 to 64 bits, and float16, float32, and float64. Multibyte values are little-endian, floating values must be finite, and the byte length must exactly match the shape and dtype.

Episode-local state​

Episode 0 new process → make_policy() → act() × N → destroy
Episode 1 new process → make_policy() → act() × N → destroy
Episode N new process → make_policy() → act() × N → destroy

A Policy may retain history, recurrent state, search trees, caches, or temporary parameters between act() calls in the same Episode. No state crosses into another Episode.

Cross-Episode learning belongs to the outer Coding Agent, which authors and submits a new immutable Program.

Action semantics​

The Environment receives the complete, unmodified Action returned by Policy.act().

Policy.act(observation)
↓
PolicyValue validation
↓
Environment.step(action)
├── valid → trusted Step
└── invalid → InvalidAction
Policy failure; no fallback step

Invalid Actions are never clipped, repaired, sampled, or replaced.

Policy failures​

The public Policy failure codes are:

CodeMeaning
exceptionmake_policy() or act() raised.
timeoutThe Policy exceeded its Episode operation timeout.
invalid_actionThe Environment rejected the complete Action.
protocol_errorThe Policy process returned a malformed or unencodable value.

After Policy failure, the evaluator does not call Environment.step() again. Trusted Environment and execution faults remain separate and abort Evaluation.

Next​