Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.motus.lithosai.com/llms.txt

Use this file to discover all available pages before exploring further.

Motus enforces code style automatically via ruff. This page documents the conventions that ruff does not catch.

Automated enforcement

uv run ruff check .        # Lint
uv run ruff format --check . # Format check
Ruff handles formatting, import sorting, and pycodestyle. The active rule sets are:
Rule setWhat it covers
Epycodestyle errors
Fpyflakes (unused imports, undefined names)
Iisort (import ordering)
Wpycodestyle warnings
Ignored rules: E501 (line length) and E402 (module-level import position). The full configuration is in pyproject.toml under [tool.ruff].

Import ordering

Organize imports into four groups, separated by blank lines:
from __future__ import annotations          # 1. Future

import asyncio                               # 2. Standard library
import logging

from pydantic import BaseModel               # 3. Third-party

from motus.runtime import agent_task        # 4. Local/relative

if TYPE_CHECKING:                            # 5. TYPE_CHECKING block
    from motus.runtime.agent_future import AgentFuture
Ruff sorts imports within each group automatically. The TYPE_CHECKING block goes last and contains imports used only in type annotations.

Type annotations

Use modern Python 3.12+ syntax throughout:
# Correct
name: str | None
items: list[Tool]
mapping: dict[str, int]

# Incorrect — do not use
name: Optional[str]
items: List[Tool]
mapping: Dict[str, int]
Use TYPE_CHECKING guards for forward references that cause circular imports:
from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from motus.runtime.agent_future import AgentFuture

Naming conventions

ElementConventionExample
ClassesPascalCaseTaskPolicy, AgentFuture
Functions / methodssnake_caseregister_hook, _deep_unwrap
ConstantsUPPER_SNAKE_CASEDEFAULT_POLICY, MODEL_CALL
Private internals_ prefix_prerequisites, _scan_deps
Type aliasesPascalCaseHookCallback, TaskType

Docstrings

Use Google style. Required for all public classes and functions.
def register_hook(event: str, callback: HookCallback) -> None:
    """Register a lifecycle hook for the given event.

    Args:
        event: The event name to listen for (e.g., "task_start").
        callback: A callable invoked when the event fires.

    Raises:
        ValueError: If the event name is not recognized.
    """
Docstrings are not required for private helpers (prefixed with _) or test functions.

Comments

Add comments only where the logic is not self-evident from the code. Do not add comments to code you did not change. Prefer renaming variables or extracting functions over writing explanatory comments.
# Good — explains a non-obvious constraint
# AgentFuture overrides __eq__/__hash__ as sync barriers,
# so never use set() or dict keys with AgentFuture instances.
pending: dict[int, AgentFuture] = {}

# Bad — restates the code
# Increment the counter
counter += 1

String formatting

Use f-strings for interpolation. Use explicit str.format() only when the template is defined separately from its arguments.
# Correct
msg = f"Task {task.name} failed after {elapsed:.2f}s"

# Correct — template defined elsewhere
TEMPLATE = "Task {name} completed in {duration}s"
msg = TEMPLATE.format(name=task.name, duration=elapsed)