Skip to content

codenib.agent.tools

Always-on default tool primitives for the agent.

This package is deliberately separate from codenib/agent/skills/ — and tools are now a separate type (:class:ToolSpec), not SkillMetadata:

  • tools/ (here) — always-on primitives that scan the raw filesystem (read, grep, glob, bash — the mainstream Claude Code tool shapes). They carry no index_requirements, no operator, and no retrieval skill_type; they are never loaded from config.yaml/executor.py packages, and are never dropped by the allow_skills / exclude_skills filters. They live in a :class:ToolRegistry the runner holds alongside its SkillRegistry.
  • skills/ — index-backed retrieval skills (bm25_search, embedding_search, find_callers, ...) declared as config.yaml + executor.py packages, gated by their declared index resources, and exposed through the SkillRegistry.

The runner exposes both to the model and dispatches over both, but they are two concepts with distinct lifecycles (skills reset per query; tools are static). See :func:ensure_default_tools_registered.

Modules:

Name Description
defaults

Always-on default tool primitives: read / grep / glob / bash.

spec

Tool primitives — a type distinct from retrieval skills.

Classes:

Name Description
ToolInputSpec

Type specification for a single tool input.

ToolRegistry

Catalogue of :class:ToolSpec objects, separate from the skill registry.

ToolSpec

An always-on filesystem/shell primitive exposed to the agent.

Functions:

Name Description
ensure_default_tools_registered

Register default tools into registry if not already present.

get_default_tool_specs

Return fresh :class:ToolSpec objects for all default tools.

ToolInputSpec dataclass

ToolInputSpec(
    name: str,
    type_hint: str,
    required: bool = True,
    default: Any = None,
    description: str = "",
    enum: list[str] | None = None,
)

Type specification for a single tool input.

Mirrors SkillInputSpec so tool_schema can emit a JSON-Schema for skills and tools with one code path.

ToolRegistry

ToolRegistry()

Catalogue of :class:ToolSpec objects, separate from the skill registry.

A plain instance (not a singleton): the runner builds one per construction and populates it with the default tools. Mirrors the small query surface of SkillRegistry (register / get / list_tools / has) so the runner can treat the two registries uniformly where it needs to.

Source code in codenib/agent/tools/spec.py
def __init__(self) -> None:
    self._tools: Dict[str, ToolSpec] = {}

ToolSpec dataclass

ToolSpec(
    tool_id: str,
    executor_fn: Callable[..., Any],
    inputs: list[ToolInputSpec] = list(),
    tool_doc: str = "",
    output_type_hint: str = "str",
    defaults: dict[str, Any] = dict(),
    description: str = "",
)

An always-on filesystem/shell primitive exposed to the agent.

Unlike a skill, a tool has no index dependency, no physical operator, and no place in the retrieval-pipeline taxonomy — it is a primitive the model is pretrained on. Its output is a scalar string, not a node list.

ensure_default_tools_registered

ensure_default_tools_registered(registry: ToolRegistry) -> None

Register default tools into registry if not already present.

Safe to call multiple times (idempotent): skips any tool already in the registry. Called by :class:~codenib.agent.runner.AgentRunner during __init__ so that the default tools (read, grep, glob, bash) are available regardless of which Ax skill subset is loaded.

Source code in codenib/agent/tools/defaults.py
def ensure_default_tools_registered(registry: ToolRegistry) -> None:
    """Register default tools into *registry* if not already present.

    Safe to call multiple times (idempotent): skips any tool already in the
    registry. Called by :class:`~codenib.agent.runner.AgentRunner` during
    ``__init__`` so that the default tools (``read``, ``grep``, ``glob``,
    ``bash``) are available regardless of which ``Ax`` skill subset is loaded.
    """
    for spec in get_default_tool_specs():
        if not registry.has(spec.tool_id):
            registry.register(spec)

get_default_tool_specs

get_default_tool_specs() -> list[ToolSpec]

Return fresh :class:ToolSpec objects for all default tools.

Returns a new list on every call so callers can safely mutate it.

Source code in codenib/agent/tools/defaults.py
def get_default_tool_specs() -> List[ToolSpec]:
    """Return fresh :class:`ToolSpec` objects for all default tools.

    Returns a new list on every call so callers can safely mutate it.
    """
    return [
        _build_read_tool(),
        _build_grep_tool(),
        _build_glob_tool(),
        _build_bash_tool(),
    ]