> ## Documentation Index
> Fetch the complete documentation index at: https://simplellmfunc.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 运行时原语

> 使用自定义 PrimitivePack 扩展 Agent 运行时

# 运行时原语

Primitives 是可以在 `execute_code`（PyRepl）内部通过 `runtime.<namespace>.<name>(...)` 调用的函数。它们让工具能够在不打破工具边界的情况下访问 Agent 级别的能力。

## 概念

| 概念                          | 含义                                        |
| --------------------------- | ----------------------------------------- |
| **PrimitivePack**           | 一组相关原语及其后端的命名集合                           |
| **RuntimePrimitiveBackend** | PrimitivePack 所包装的有状态对象（例如 SelfReference） |
| **@primitive**              | 将函数注册为可调用原语的装饰器                           |
| **PrimitiveSpec**           | 暴露给模型的契约（名称、描述、参数、最佳实践）                   |
| **PrimitiveCallContext**    | 传递给原语处理函数的运行时上下文                          |

## 内置原语：SelfRef Pack

框架内置了一个 Pack —— `selfref` —— 提供 6 个原语：

```
runtime.selfref.context.inspect()
runtime.selfref.context.remember(text)
runtime.selfref.context.forget(experience_id)
runtime.selfref.context.compact(goal, instruction, ...)
runtime.selfref.fork.spawn(task, instruction, ...)
runtime.selfref.fork.gather_all(include_history=False)
```

## 创建自定义 Pack

### 1. 定义 Backend

```python theme={null}
from SimpleLLMFunc.runtime import RuntimePrimitiveBackend


class MetricsBackend(RuntimePrimitiveBackend):
    def __init__(self):
        self.counters: dict[str, int] = {}

    def increment(self, name: str, amount: int = 1) -> int:
        self.counters[name] = self.counters.get(name, 0) + amount
        return self.counters[name]

    def get_all(self) -> dict[str, int]:
        return dict(self.counters)
```

### 2. 定义 Primitives

```python theme={null}
from SimpleLLMFunc.runtime import primitive, PrimitiveCallContext


@primitive
async def increment_counter(
    ctx: PrimitiveCallContext,
    name: str,
    amount: int = 1,
) -> dict:
    """
    Increment a named counter and return its new value.

    Args:
        name: Counter name.
        amount: How much to add. Default 1.

    Returns:
        Dict with counter name and new value.

    Best Practices:
        - Use descriptive counter names (e.g., "files_processed", "errors_found").
        - Use this to track progress across tool calls.
    """
    backend: MetricsBackend = ctx.backend
    new_value = backend.increment(name, amount)
    return {"name": name, "value": new_value}


@primitive
async def get_metrics(ctx: PrimitiveCallContext) -> dict:
    """
    Get all current counter values.

    Returns:
        Dict of all counter names to their current values.

    Best Practices:
        - Call this to report progress summaries.
        - Useful before context compaction to record final metrics.
    """
    backend: MetricsBackend = ctx.backend
    return backend.get_all()
```

<Warning>
  Primitive 的 docstring **必须**包含 `Best Practices` 部分。缺少该部分将导致注册失败。
</Warning>

### 3. 构建 Pack

```python theme={null}
from SimpleLLMFunc.runtime import PrimitivePack

metrics_pack = PrimitivePack(
    namespace="metrics",
    backend=MetricsBackend(),
    primitives=[increment_counter, get_metrics],
    guide={
        "namespace": "metrics",
        "overview": "Track numeric counters across tool calls.",
        "best_practices": {
            "when_to_use": "To track progress, count occurrences, or measure work done.",
            "pattern": "Increment during work, get_metrics at milestones.",
        },
    },
)
```

### 4. 安装到 PyRepl

```python theme={null}
from SimpleLLMFunc.builtin import PyRepl

repl = PyRepl()
repl.install_primitive_pack(metrics_pack)
```

现在模型可以调用：

```python theme={null}
runtime.metrics.increment_counter("files_read")
runtime.metrics.get_metrics()
```

## 可发现性

模型通过内置的元原语来发现可用的 Primitives：

```python theme={null}
runtime.list_primitives()              # 所有可用的原语名称
runtime.get_primitive_spec("metrics.increment_counter")  # 完整契约
runtime.list_backends()                # 已安装的 backend packs
```

Spec 中包含参数描述、返回类型和最佳实践——足以让模型在无需预训练的情况下正确使用原语。

## PrimitiveCallContext

每个原语处理函数都会接收一个上下文对象：

```python theme={null}
@dataclass
class PrimitiveCallContext:
    backend: RuntimePrimitiveBackend   # Pack 的 backend 实例
    fork_context: Optional[ForkContext]  # Fork 信息（如果在 fork 内部）
    event_emitter: ToolEventEmitter    # 发送自定义事件
```

使用 `ctx.event_emitter` 可以在长时间运行的原语中流式推送进度。

→ [API 参考：Runtime](/zh/api/runtime)
