Extension Points

Extension Points

Overview

This document describes extension points in LevPRO AI runtime. Prefer MCP servers for new agent capabilities; keep Core native tools limited to meta/recovery.

Architecture Summary

[ INFRA ]     packages/llama-tools/llama_tools/planner/, packages/local-ai-core/core/
[ CORE ]      core/token_counter.py, core/context_builder.py
[ APP ]       packages/local-ai-core/agents/loop.py, tools/executor.py
[ STORAGE ]   packages/local-ai-core/session/, packages/local-ai-memory/memory/ (optional)
[ TOOLS ]     native meta/archive/memory recovery + mcp_* (local-ai-mcp)
[ SECURITY ]  security/guard.py, security/approval.py

Adding capabilities (preferred: MCP)

  1. Add a server to the host's mcp.json (stdio command/args/env or HTTP url/headers).
  2. Point Core at the file (mcp.external_path, --mcp-config, or LOCAL_AI_MCP_CONFIG).
  3. Tools appear as mcp_{server}_{tool} and are auto-granted.

See mcp.md and host_integrations.md.


Adding a Native Tool (rare)

Use only for meta/recovery tools that must live in Core (not filesystem/shell/git/HTTP).

  1. Define a Tool / LazyTool under tools/ (see meta_tools.py / session tools).
  1. Register via create_meta_tools(), memory/session stack, or extra_tools in app.pybuild_tool_executor().
  1. Auto-grant in agents/registry.py / AgentLoop if always available.
  1. Document in host prompt_files (copy bundled templates; do not edit site-packages). Update Core bundled templates only when changing package defaults.
  1. Test in packages/local-ai-core/tests/.
from tools.schema import Tool

async def my_meta_tool(reason: str) -> str:
    return f"noted: {reason}"

TOOL = Tool(
    name="my_meta_tool",
    description="Example native meta tool",
    input_schema={
        "type": "object",
        "properties": {"reason": {"type": "string"}},
        "required": ["reason"],
        "additionalProperties": False,
    },
    func=my_meta_tool,
)

Do not reintroduce built-in read_file / run_script / git / net packages.


Adding a New Agent

  1. Add agent config in config.yaml:
agents:
  assistant:
    tools: []
  coder:
    tools: []
    model: main   # when ensemble.enabled
memory:
  enabled: true
  categories: ["knowledge"]

mcp_* tools are auto-granted; tools: is for explicit native names when needed.

  1. Add tests in packages/local-ai-core/tests/test_agent_loop.py as needed.

Adding a New Interface

CLI Interface

  1. Add subparser in main.py.
  1. Create interface in interfaces/newcommand.py following docs/bootstrap.md. Apply CLI overrides before create_app().
import argparse
import asyncio

from agents.registry import get_agent_config
from app import create_app, default_agent_name
from config.loader import load_config
from config.overrides import apply_cli_overrides
from core.shutdown import install_signal_handlers


async def main_async(args: argparse.Namespace) -> None:
    config = apply_cli_overrides(load_config(args.config), args)
    ctx = create_app(config=config)
    install_signal_handlers(ctx)
    await ctx.start_supervisors()
    await ctx.startup()
    try:
        agent_config = get_agent_config(ctx.config, default_agent_name(ctx.config))
        result = await ctx.session_runner.run(
            args.user_id,
            "session_123",
            f"Do something with {args.arg}",
            agent_config,
            agent_name=default_agent_name(ctx.config),
        )
        print(result.response)
    finally:
        await ctx.shutdown()
  1. Register in main.py.

Optional packages (non-tool stacks)

Optional features ship as separate pip packages. Each exposes a build_* entry point wired in app.py via try/import + config gate:

Extra Package Config gate Entry point
[memory] local-ai-memory memory.enabled: true build_memory_stack()
(hard dep) local-ai-mcp mcp.enabled + servers from mcp.json build_mcp_stack()
[ensemble] local-ai-ensemble ensemble.enabled: true build_ensemble_stack()
[skills] local-ai-skills skills.enabled: true build_skills_stack()
[monitor] local-ai-monitor monitor.enabled: true build_monitor_stack()
[autotune] local-ai-autotune llama.autotune.enabled build_autotune_stack()

Pattern to add a new optional non-capability extra (routing, monitoring, memory, etc.):

  1. Implement feature in packages/local-ai-<name>/ with a build_*() entry point
  2. Add config dataclass to config/loader.py
  3. Wire in app.py via try/import + config gate
  4. Add extra in local-ai-core pyproject.toml
  5. Document in docs/<name>.md

For agent capabilities, add an MCP server instead of a Core package.

See: mcp.md, host_integrations.md, ensemble.md, skills.md, memory.md, monitor.md.

Embedding via SessionRunner

result = await ctx.session_runner.run(
    user_id="user1",
    session_id="session_123",
    user_input="Hello",
    agent_config=agent_config,
    agent_name="assistant",
    resume=False,
)

Use ctx.agent_loop.run(...) only for low-level tests. See docs/bootstrap.md.


Adding New Configuration Options

  1. Add to dataclass in config/loader.py
  2. Add to config.yaml / config.example.yaml
  3. Thread through create_app() as needed

Adding New Logging Events

  1. Add event tag in core/logging_config.py EVENT_TAGS
  2. Use log_event(logger, "MY_EVENT", "...")

Summary

All extensions must:

  1. Follow architectural rules — no forbidden frameworks / regex tool parsing
  2. Prefer MCP for capabilities
  3. Be well-tested and documented
  4. Be type-safe and async-first
  5. Route runtime file I/O through DirectoryGuard when applicable

Related: architecture.md, architecture_rules.md, AGENTS.md.