Engineering and security learning path

The preceding lessons answered “How does nanobot complete one Turn?” This section changes perspective: when requests arrive concurrently, a user stops midway, a Provider fails temporarily, the process shuts down, or the model tries to access outside the workspace, how does the system avoid disorder and data damage?

Corresponding source

Risk topicSource
Concurrency, cancellation, and Turn resourcesnanobot/agent/loop.py, nanobot/agent/runner.py
Provider, Tool, and persistence failuresnanobot/providers/base.py, nanobot/agent/tools/, nanobot/session/manager.py
Observability and testsnanobot/bus/runtime_events.py, nanobot/agent/hook.py, tests/
Workspace, Shell, and SSRFnanobot/security/, nanobot/agent/tools/shell.py, sandbox.py
Packaging and frontend buildpyproject.toml, hatch_build.py, webui/, nanobot/web/

Learning objectives

After this section, you should be able to:

  • draw nanobot’s primary concurrency boundaries;
  • distinguish timeout, cancellation, recoverable failure, and unrecoverable failure;
  • choose an observation point from logs, state traces, runtime events, and persisted files;
  • explain what the workspace guard, Shell sandbox, and SSRF guard each protect;
  • understand how the Python package, WebUI assets, and Bridge enter a release artifact.

Prerequisites

OrderLessonCore question
1asyncio concurrency, cancellation, and cleanupWhich work can run concurrently, and which must be serialized?
2Errors, retries, and data consistencyAfter failure, should the system retry, fall back, persist, or stop?
3Logging, runtime events, and testingWhich evidence layer should you observe?
4Workspace, Shell, and SSRF security boundariesWhat does “restricted to the workspace” actually guarantee?
5Packaging, WebUI build, and cross-platform behaviorHow does source become an installable, runnable product?

Engineering risk map

flowchart LR
    A["Concurrent requests"] --> A1["Session Lock"]
    A --> A2["Global Semaphore"]
    A --> A3["Tool concurrency_safe"]

    B["Interruption and shutdown"] --> B1["Task.cancel"]
    B --> B2["Restore runtime checkpoint"]
    B --> B3["Close MCP / Channel"]
    B --> B4["Session flush_all"]

    C["External failure"] --> C1["Provider retry"]
    C --> C2["Fallback"]
    C --> C3["Convert error to visible result"]

    D["Untrusted input"] --> D1["Tool schema"]
    D --> D2["Workspace guard"]
    D --> D3["SSRF guard"]
    D --> D4["Shell sandbox"]

    E["Process crash"] --> E1["Temporary file"]
    E --> E2["os.replace"]
    E --> E3["fsync when required"]

These mechanisms are not one “security layer.” A Session Lock prevents concurrent writes to one conversation but cannot stop the model from reading a private file. The SSRF guard blocks private-network targets but does not constrain the content of an ordinary public request.

Fact boundaries for this section

An application-level guard is not operating-system isolation

When restrictToWorkspace is enabled without a system sandbox, nanobot applies path resolution and command checks at the application layer. The source explicitly reports this state as application with enforced=False. Do not present it as an unbypassable OS security boundary.

There is no universal transaction layer

Session, Cron, Memory, configuration, and WebUI state use separate write strategies. One file using os.replace does not prove equal durability for all state.

Primary source entry points

  • nanobot/agent/loop.py
  • nanobot/agent/runner.py
  • nanobot/providers/base.py
  • nanobot/session/manager.py
  • nanobot/cron/service.py
  • nanobot/agent/tools/shell.py
  • nanobot/agent/tools/sandbox.py
  • nanobot/security/workspace_access.py
  • nanobot/security/workspace_policy.py
  • nanobot/security/network.py
  • nanobot/cli/commands.py
  • pyproject.toml
  • webui/vite.config.ts

Next: asyncio concurrency, cancellation, and cleanup