Skip to main content
Runtime primitives are SimpleLLMFunc’s built-in runtime capabilities for CodeAct-style execution. They are not exposed directly as @tool; instead, they are accessed from inside PyRepl.execute_code(...) through the runtime.* namespace.
LLM -> execute_code -> runtime.<pack>.<primitive>(...)

What They Are For

In CodeAct mode, the model writes Python code and executes it through execute_code. Runtime primitives are the runtime APIs available from that code, for example:
runtime.selfref.context.inspect()
runtime.github_repo.list_open_issues("owner/repo")

Runtime Entry Point

Access capabilities directly from runtime.* without imports.

CodeAct Built-in Capability

Hosted by PyRepl and reached indirectly through execute_code.

Discoverable by the Model

Exposed through runtime.get_primitive_spec(...) and runtime.list_primitive_specs(...).

Key Concepts

A PrimitivePack is a namespace for runtime primitives.
  • It defines the runtime.<pack_name>.<primitive_name> prefix
  • It can bind a default backend
  • It can carry guidance that explains the mental model and boundaries of the pack
A primitive is an individual runtime function under a pack.
runtime.<pack_name>.<primitive_name>(...)
It is implemented as a regular Python function that also receives a PrimitiveCallContext.
A backend is the Python object that provides the real capability, such as a service client, state container, or custom class instance. Primitive handlers usually access it through ctx.backend or ctx.get_backend(...).
1

Create a pack

Use repl.pack(name, backend=..., guidance="...") to create a namespace and backend binding.
2

Register primitives

Add one or more runtime functions with @pack.primitive(...).
3

Install into PyRepl

Mount the pack with repl.install_pack(pack).
Example:
from SimpleLLMFunc.builtin import PyRepl


class GitHubRepoAPI:
    def list_open_issues(self, repo: str) -> list[dict[str, str]]:
        return [
            {"id": "42", "title": "Bug: tool timeout", "repo": repo},
            {"id": "57", "title": "Docs: update primitive guide", "repo": repo},
        ]

    def get_issue(self, repo: str, issue_id: str) -> dict[str, str]:
        return {"id": issue_id, "title": "Example issue", "repo": repo}


repl = PyRepl()

github_repo = repl.pack(
    "github_repo",
    backend=GitHubRepoAPI(),
    guidance="github_repo = repository issue/query primitives backed by GitHubRepoAPI.",
)


@github_repo.primitive("list_open_issues", description="List open issues from a GitHub repository.")
def list_open_issues(ctx, repo: str) -> list[dict[str, str]]:
    backend = ctx.backend
    if not isinstance(backend, GitHubRepoAPI):
        raise RuntimeError("backend must be a GitHubRepoAPI")
    return backend.list_open_issues(repo)


@github_repo.primitive("get_issue", description="Read one issue by id from a GitHub repository.")
def get_issue(ctx, repo: str, issue_id: str) -> dict[str, str]:
    backend = ctx.backend
    if not isinstance(backend, GitHubRepoAPI):
        raise RuntimeError("backend must be a GitHubRepoAPI")
    return backend.get_issue(repo, issue_id)


repl.install_pack(github_repo)

# Called from execute_code:
# runtime.github_repo.list_open_issues("owner/repo")
# runtime.github_repo.get_issue("owner/repo", "42")
For lightweight cases, you can also use @repl.primitive(...) directly.

Where They Are Used

Exposes the runtime.* namespace inside the execution environment.
The model reaches primitives only after deciding to call execute_code.
runtime.selfref.context.* and runtime.selfref.fork.* are built-in examples of the same mechanism.

Primitive Context Injection

Each primitive handler receives a PrimitiveCallContext, which typically includes:
  • primitive_name
  • call_id / execution_id
  • event_emitter
  • repl / registry
  • backend_name
  • backend
The lookup flow is roughly:
worker -> PyRepl._execute_primitive_call -> PrimitiveRegistry.call
-> context.backend_name / context.backend resolution
Prefer accessing runtime dependencies through ctx.backend or ctx.get_backend(...) instead of looking them up manually. That keeps fork, clone, and lifecycle behavior predictable.

Contracts and Discoverability

Use:
  • runtime.get_primitive_spec(name) for a single primitive
  • runtime.list_primitive_specs(...) for batches of primitives
The default output format is XML, and format='dict' can be used for structured fields.
  • The handler docstring
  • PrimitiveContract
  • Explicit arguments on @primitive(...)
  • PrimitiveContract: the author-side structured definition
  • PrimitiveSpec: the normalized runtime/public specification actually consumed by the model
The docstring format commonly includes:
  • Use:
  • Input:
  • Output:
  • Parse:
  • Parameters:
  • Best Practices:
Best Practices must come from the docstring and are required for registration.

How Primitives Enter Prompt Context

Primitives themselves are not injected directly into the system prompt. What usually gets injected is tool guidance, especially from execute_code. In practice, primitive guidance reaches the model through two paths:
  1. execute_code best practices that tell the model how to inspect primitive contracts
  2. runtime queries such as runtime.get_primitive_spec(...) and runtime.selfref.guide()
If you need some primitive guidance to be strongly injected, put it in tool best practices or a prompt_injection_builder.