Simulation Extensibility API Reference¶
This page is a developer-facing API reference for extending simulation structure in code. It is separate from workflow guides such as Environment Layer and Building Agents.
Use this reference when adding new agent runtimes, backend apps, game masters, GM components, engines, engine policies, or probe/evaluator code.
Reference Map¶
| Layer | Primary modules |
|---|---|
| Agents | src/silisocs/agents/base_agent.py, agents/native.py, agents/fixed.py |
| Agent builders | src/silisocs/runtime/construction/agent_builders/ |
| Environment apps | src/silisocs/environments/backends/base.py, environments/backends/factory.py |
| GMs | src/silisocs/environments/gm/base_game_master.py, gm/game_master.py |
| GM components | src/silisocs/environments/gm/components/ |
| Engines | src/silisocs/simulation_engines/base_engines.py, simulation_engines/runtime_base.py |
| Engine policies | src/silisocs/simulation_engines/policies/loops.py, steps.py, turns.py, probe_schedule.py |
1) Agents API¶
All agent runtimes must implement silisocs.agents.base_agent.Agent:
class Agent(ABC):
@property
def name(self) -> str: ...
def observe(self, observation: str) -> None: ...
def act(self, action_spec: ActionSpec) -> ActionOutput: ...
act() returns an ActionOutput. Native agents usually assemble their context
inside act() and call self._call_model(context, action_spec), which routes
the typed ActionSpec to the configured LanguageModel. Custom runtimes with
internal state should also implement
get_state() and set_state(state) for checkpoint resume.
Native configs instantiate runtime classes directly with class_path and
params. Reference implementations live in src/silisocs/agents/native.py
and src/silisocs/agents/fixed.py. Concordia-style prefab agents are supported
only behind compat: concordia and the optional Concordia adapter.
Language Model API¶
All model providers implement silisocs.runtime.language_models.LanguageModel.
Agents do not call provider-specific clients directly; they use _call_model(...)
or, for custom low-level behavior, the typed model methods:
sample_text(prompt, **kwargs) -> str
sample_choice(prompt, responses, **kwargs) -> tuple[int, str, dict[str, float]]
sample_tool_calls(prompt, tools, *, mode="single", **kwargs) -> list[ToolCall]
sample_structured(prompt, schema, **kwargs) -> dict[str, Any]
Use ScriptedLanguageModel for deterministic tests, OpenAILanguageModel for
the OpenAI API, OpenAICompatibleLanguageModel for compatible local or hosted
endpoints, and NoLanguageModel only when an agent never needs model output.
Unsupported typed outputs should raise rather than silently returning dummy data.
Agent Builder API¶
Agent builders translate config into construction specs. They do not instantiate
live agents and they do not receive the model. Subclass
silisocs.runtime.construction.agent_builders.AgentBuilder and implement:
The default PersonaPipelineAgentBuilder handles inline/config/file/Hugging Face
records, field mapping, shared/specific memories, and fixed-action plan rendering.
Custom builders may call it internally, then append additional AgentConfig
records. Runtime assembly remains responsible for loading classes, injecting the
LanguageModel, and wrapping explicit Concordia-compatible agents.
2) Environment App API¶
The core backend contract is BackendApp in
src/silisocs/environments/backends/base.py.
Common backend setup hook:
Common optional hooks:
observe(actor_name: str, **kwargs) -> strupdate(step: int, agent_names: Sequence[str], context=None) -> None
Timeline/recommendation capability methods live on SocialBackendApp, not on
plain BackendApp:
get_timeline(user_name: str, limit: int = 10) -> list[dict]get_timeline_mode(...) -> list[dict]format_timeline_for_observation(timeline: list[dict]) -> strparse_and_resolve_action(user_name: str, action_data: dict) -> str
Expose executable actions with @app_action. generic_action and
tool_calling resolve modes discover those actions automatically.
If an action needs the acting identity, include an agent_name: str parameter;
the resolver injects it from the active Agent Name and omits it from
agent-facing prompts/tool schemas. Target parameters such as target_user
remain agent-visible.
SocialBackendApp subclasses BackendApp for backends that use the
timeline/recommendation GM components. Backends that do not need those
components should subclass BackendApp directly.
Custom app config:
params are strict constructor arguments. Unknown keys fail before simulation
startup unless the target class accepts **kwargs.
3) Game Master API¶
Base class: BaseGameMaster
Module: src/silisocs/environments/gm/base_game_master.py
Direct GM methods live on ComponentGameMaster. MultiFlowGameMaster keeps
the same public methods and routes component slots by agent flow:
acting_agents(...): chooses active actors.action_prompt(agent_name): emits typedActionSpec.make_observation(agent_name): computes per-agent observation text.resolve_action(agent_name, action): dispatches typedActionOutput.update(step, agents, context): runs pre-turn environment updates.initialize(agents, context): initializes backend/app state through the Game Master'scomponents.initializeslot.
Important integration fields used by engines/components:
backendagent_flow_tagsflow_to_component_map
GMs should keep state minimal: the backend, typed component slots, routing
metadata, and optional get_state/set_state hooks. They should not read the
Hydra config directly; construction code passes normalized params into backend
and component constructors.
4) GM Component API¶
Factory module: src/silisocs/environments/gm/components/factory.py
Public builders:
build_initialize_component(...)build_initialize_components(...)build_action_prompt_component(...)build_observe_component(...)build_observe_components(...)build_resolve_component(...)build_next_acting_component(...)build_update_component(...)
Config schema pattern:
<slot_name>:
built_in: <registered_name>
class_path: <optional.module.Class>
params: {}
instances: {} # optional, for flow-routed GMs
flow_map: {} # optional, maps flow names to instance keys
params are strict constructor arguments. Unknown keys fail early unless the
target component accepts **kwargs. Runtime-injected values such as model,
agent_names, and app handles may still be filtered when a constructor does
not accept them. Observe components that explicitly accept observation_params
may use params as a forwarded observation-settings bag.
Built-in component names:
initialize:social_media,app_initialize,disabled,noneaction_prompt:defaultobserve:app_observation,timeline_every_turn,episode_onlyresolve:parsed_action,generic_action,tool_callingnext_acting:activity_markov,activity_probability,all_agents,fixed_orderupdate:social_recommendation,disabled,none
Generic component bases and defaults live directly under
silisocs.environments.gm.components. Social-media-only components live under
silisocs.environments.gm.components.social_media but keep the same built-in
YAML names.
Subcomponent interfaces in components/base.py:
BaseComponent.get_state()andBaseComponent.set_state(...)InitializeComponent.initialize(...)NextActingComponent.acting_agent_names()ActionPromptComponent.action_prompt(agent_name)ObservationComponent.make_observation(agent_name)ResolveComponent.resolve_action(agent_name, action)UpdateComponent.update(step, agents, context)
Default baselines are available for backends that only need BackendApp:
AppInitializeComponentcalls a backend'sinitialize(...).AllAgentsNextActing,FixedOrderNextActing,ActivityProbabilityNextActing, andActivityMarkovNextActingselect agents without social timeline logic.AppObservationComponentdelegates toBackendApp.observe(...).EpisodeObservationreturns episode-index observations for scripted flows.- generic action and tool-calling resolvers dispatch backend actions discovered
through
@app_action. AppUpdateComponentdelegates toBackendApp.update(...).NoOpUpdateComponentis the explicit update slot for environments that do not need pre-turn state refresh.
Social-media-specific defaults are intentionally isolated under
components.social_media: TimelineMakeObservation and
SocialRecommendationUpdateComponent. They require a SocialBackendApp.
Use BaseComponent.get_state() / set_state(...) only for component-owned
state that must survive checkpoint resume, such as a fixed-order index. Backend
domain state should live in the backend.
Runtime bootstrap extensions live under silisocs.initialization:
initialization.agents.AgentInitializerinitialization.game_masters.GameMasterInitializerStrategyinitialization.game_masters.GameMasterInitializerinitialization.simulation.SimulationInitializer
The Engine runs those phases in order: agents, Game Masters, then simulation.
Seed posts are simulation initialization and are posted through
GameMaster.resolve_action(...).
Initializer contracts:
- Agent initializers receive agents plus
AgentInitializationContext, mutate agent memory/observations by callingagent.initialize(...), and returnNone. - Game Master phase strategies receive GMs, agents, and the initialization
context, then call each GM's
initialize(...). The GM delegates backend setup to its initialize component. - Simulation initializers receive agents, GMs, and context after backend setup. Seed-post initializers generate or load seed text and post it through normal GM resolution, so backend action logs keep the same shape as in-loop actions.
5) Engine API¶
Modules:
src/silisocs/simulation_engines/base_engines.py: concreteRuntimeEngineplus preset wrappers.src/silisocs/simulation_engines/runtime_base.py: shared dataclasses and protocols, includingAgentStepResult,StepBatch, andStepResult.src/silisocs/simulation_engines/policies/loops.py: loop policies.src/silisocs/simulation_engines/policies/steps.py: step policies.src/silisocs/simulation_engines/policies/turns.py: turn policies.
Factory entrypoint: build_engine(cfg) in
src/silisocs/runtime/construction/engines.py.
RuntimeEngine provides startup initialization, per-step GM updates,
per-agent observe/act/resolve, action concurrency, retry telemetry, and probe
phase orchestration. The preset wrappers select default step policies:
BaseRuntimeEngine uses base scheduling, FlowRuntimeEngine uses flow
scheduling, and MultiGMRuntimeEngine uses multi-GM flow routing.
6) Engine Policy API¶
Loop policies own the outer episode lifecycle and implement:
def run(
*,
engine: Any,
game_masters: list[Any],
agents: list[Any],
max_steps: int,
start_step: int,
verbose: bool,
checkpoint_callback: Any | None,
) -> None: ...
Step policies own one episode step and implement:
def run(
*,
engine: Any,
step_index: int,
game_masters: list[Any],
agents: list[Any],
verbose: bool,
) -> StepResult: ...
Most custom step policies should call engine._execute_batches(...) with a
sequence of StepBatch(flow_name, game_master, turns). Each turns entry is
(agent, action_spec). Calling _execute_batches(...) keeps standard action
logging, retry telemetry, concurrency limits, and StepResult shape. A custom
step policy may bypass it, but then it owns those responsibilities.
Turn policies own one selected agent's action cadence and implement:
def run(
*,
engine: Any,
game_master: Any,
agent: Any,
action_spec: Any,
verbose: bool,
) -> str: ...
Most custom turn policies should call
engine.run_agent_step(game_master=..., agent=..., action_spec=..., verbose=...).
That helper performs observation, agent.act(...), GM resolution, and result
observation. A custom turn policy may bypass it only when it intentionally owns
the full observe/act/resolve cycle.
Probe-schedule policies live in
src/silisocs/simulation_engines/policies/probe_schedule.py and implement:
Built-ins:
- Loop policy:
fixed_steps - Step policy:
base,sequential,flow,multi_gm - Turn policy:
single_action,fixed_count,open_ended - Probe schedule:
step_schedule,fixed_interval,disabled
Turn policy params include observe_before_act: first | always | never.
first is the default and preserves existing behavior for repeated actions.
Policy factories support built_in, optional class_path, and strict
constructor validation for configured params.
7) Extension Recipes¶
Add a custom backend app:
- Subclass
BackendApp. - Implement
initialize(...). - Implement
observe(...)and optionallyupdate(...). - Add
@app_actionmethods. - Configure
env.gm.backend.class_pathandenv.gm.backend.params.
Add a custom GM component:
- Implement a native context component or initializer hook.
- Point
env.gm.components.<slot>.class_pathto the class. - Put public constructor settings under
params.
Add a custom turn policy:
Add a custom sequential-style step policy:
from silisocs.simulation_engines.runtime_base import StepBatch, StepResult
class MySequentialStepPolicy:
name = "my_sequential"
def run(self, *, engine, step_index, game_masters, agents, verbose) -> StepResult:
del step_index, verbose
gm = game_masters[0]
turns = engine._selected_turns(game_master=gm, candidate_agents=agents)
batches = [
StepBatch(flow_name=f"agent:{agent.name}", game_master=gm, turns=[turn])
for turn in turns
for agent, _spec in [turn]
]
return engine._execute_batches(step_index=0, batches=batches, verbose=False)
Add a custom probe schedule policy by implementing should_run_probe_phase(...)
and configuring eval.probes.schedule.class_path.
Add a custom probe type:
- Subclass
ProbeBase. - Implement
form_question_for_agent(agent)andparse_answer(raw_response). - Register the module with
eval.probes.probe_lib_module.
Probe prompts should ask the measurement question and any answer-format constraint. Do not inject agent identity text into probes; agents supply their own identity/persona context when they act.
8) Compatibility Checklist¶
- Keep method signatures aligned with factory call sites.
- Treat
paramsas strict public API; add**kwargsonly when intentionally accepting arbitrary config keys. - Preserve checkpoint state contracts (
get_state/set_state) when stateful. - Add targeted tests for factory construction and runtime behavior.
- Update this page when adding new built-ins or extension hooks.
Related Docs¶
- Documentation Coverage: coverage and staleness tracker
- Framework Roadmap: near-term framework priorities
- Environment Layer: architecture and design patterns
- Building Agents: world and builder workflows
- Configuration Reference: full config keys
- Contributing: lint/test workflow and coding standards