Complete your first request with DeepSeek

Corresponding source

Runtime stepSource
nanobot command entry[project.scripts] in pyproject.toml; nanobot/cli/commands.py::agent, onboard, status
Configuration path and loadingnanobot/config/paths.py, nanobot/config/loader.py::load_config, nanobot/config/schema.py::ProvidersConfig
DeepSeek registrationThe ProviderSpec named deepseek in nanobot/providers/registry.py
Provider constructionnanobot/providers/factory.py::load_provider_snapshot, make_provider
OpenAI-compatible request implementationnanobot/providers/openai_compat_provider.py::OpenAICompatProvider

Learning objectives

After this lesson, you should be able to:

  • install nanobot from the current code-CN source;
  • use a separate configuration and workspace so the default instance remains untouched;
  • supply a DeepSeek key through an environment variable;
  • complete configuration validation, a one-shot request, and an interactive request;
  • classify a failure as installation, configuration, Provider, or Agent runtime.

Prerequisites

Never paste a real key into documentation

This lesson uses the DEEPSEEK_API_KEY environment variable. Do not put the key in Markdown, Git, screenshots, or shared logs.

1. Change to the current source directory

Set-Location "example\nanobot\code-CN"

The current pyproject.toml requires Python 3.11 or later:

python --version

2. Install the current source and development dependencies

Run this in your own Conda environment:

conda create -n nanobot-learning -c conda-forge --override-channels python=3.11 pip -y
conda activate nanobot-learning
python -m pip install -e ".[dev]"
nanobot --version

If the prompt shows both (base) and (venv), run deactivate first so python does not continue pointing to the old venv.

-e creates an editable install, so the command imports the source from the current workspace. You do not need to copy the package after reading it or changing an isolated example.

Source evidence:

  • pyproject.toml
    • requires-python = ">=3.11"
    • [project.scripts]
    • nanobot = "nanobot.cli.commands:app"

3. Create an isolated learning instance

Use a temporary directory so the default ~/.nanobot/config.json and workspace remain untouched:

$nanobotLab = Join-Path $env:TEMP "nanobot-learning"
$nanobotConfig = Join-Path $nanobotLab "config.json"
$nanobotWorkspace = Join-Path $nanobotLab "workspace"
 
New-Item -ItemType Directory -Force -Path $nanobotLab | Out-Null
nanobot onboard --config $nanobotConfig --workspace $nanobotWorkspace

This command:

  • creates a separate configuration;
  • writes the workspace location into that configuration;
  • initializes workspace templates;
  • does not modify this repository’s learning-EN or code-CN content.

Related source:

  • nanobot/cli/commands.py::onboard
  • nanobot/config/loader.py
  • nanobot/config/paths.py

4. Set the DeepSeek key

Set it only for the current PowerShell process and its child processes:

$env:DEEPSEEK_API_KEY = "paste your real key locally"

Do not save that line with its real value in a note or script.

5. Edit the learning configuration

Open $nanobotConfig and merge these fields without deleting other configuration generated by onboard:

{
  "providers": {
    "deepseek": {
      "apiKey": "${DEEPSEEK_API_KEY}"
    }
  },
  "modelPresets": {
    "learning": {
      "label": "DeepSeek Learning",
      "provider": "deepseek",
      "model": "deepseek-v4-flash",
      "reasoningEffort": "none"
    }
  },
  "agents": {
    "defaults": {
      "modelPreset": "learning"
    }
  }
}

Why these fields are explicit:

  • providers.deepseek maps to ProvidersConfig.deepseek;
  • config/loader.py resolves ${DEEPSEEK_API_KEY} during loading;
  • a named preset binds the Provider, model, and generation parameters together;
  • provider: deepseek is easier to debug on the first run than automatic inference;
  • reasoningEffort: none keeps the first request in non-reasoning mode and reduces the number of variables to observe.

The current DeepSeek Provider in nanobot has:

  • name: deepseek;
  • backend: openai_compat;
  • default API base: https://api.deepseek.com;
  • environment variable: DEEPSEEK_API_KEY;
  • registration: nanobot/providers/registry.py.

Current model names

DeepSeek’s current official models are deepseek-v4-flash and deepseek-v4-pro. The old deepseek-chat and deepseek-reasoner aliases are in a retirement phase, so this library does not use them.

External evidence:

6. Validate the configuration with an explicit request

nanobot status checks only the default instance and does not accept --config. For the learning instance, run a request with explicit paths:

nanobot agent `
  --config $nanobotConfig `
  --workspace $nanobotWorkspace `
  --message "Reply only with: nanobot is connected to DeepSeek"

Expected outcome:

  • configuration loads;
  • the Provider is created;
  • the model request succeeds;
  • one normal assistant response is printed;
  • Session and other runtime data appear under the workspace.

The exact wording may differ. Do not treat a fixed sentence as the success condition.

7. Enable runtime logs

If the request fails, add --logs:

nanobot agent `
  --config $nanobotConfig `
  --workspace $nanobotWorkspace `
  --logs `
  --message "Confirm in one sentence that you are ready."

Observe:

  • the active config path;
  • the workspace path;
  • the resolved Provider and model;
  • whether the request reached the Provider;
  • whether the failure is authentication, parameters, timeout, or Agent logic;
  • whether the Session was ultimately saved.

8. Run the interactive CLI

nanobot agent `
  --config $nanobotConfig `
  --workspace $nanobotWorkspace `
  --logs

Send these messages in order:

Remember the number 37.
Which number did I ask you to remember?

This experiment proves only that one CLI session can reuse history. It does not prove that long-term Memory is working. Later lessons explain the differences among Session, Memory, and context.

9. Observe a minimal Tool Call

Create an ordinary text file inside the learning workspace, then ask nanobot to read it. Do not point it at a real project or sensitive directory.

Set-Content -LiteralPath (Join-Path $nanobotWorkspace "hello.txt") `
  -Value "nanobot-tool-check" `
  -Encoding utf8

In the interactive CLI, ask:

Read hello.txt from the workspace root and tell me its contents.

With logs enabled, observe:

  • whether the model produces a Tool Call;
  • whether ToolRegistry finds the filesystem tool;
  • whether the resolved path remains inside the workspace;
  • whether the tool result enters the next model request;
  • whether the final text reports the correct contents.

This is not a security test

The exercise observes only the normal path. Workspace escape, Shell, and SSRF receive separate treatment in the security section.

10. Inspect the result

List the experiment directory:

Get-ChildItem -LiteralPath $nanobotLab -Recurse -Force

Identify:

  • config.json: instance configuration;
  • workspace/: Agent workspace;
  • workspace/sessions/: Session JSONL;
  • workspace templates and the memory directory;
  • cron data that may appear after a later Gateway run.

Common failures and first checks

SymptomCheck first
nanobot command not foundwhether the Conda environment is activated, editable install, python -m nanobot --version
${DEEPSEEK_API_KEY} cannot be resolvedwhether the variable is set in the current PowerShell process
401key correctness and accidental whitespace
402DeepSeek account balance
422model name, Provider arguments, or generation parameters
429request rate
500/503Provider status and retry behavior
Provider cannot be matchedwhether the preset explicitly says provider: deepseek
CLI responds but does not call a toolwhether the request requires a tool, whether the model answered directly, and whether the tool was registered

See the official DeepSeek error codes.

You should be able to explain

  1. Why use a separate config and workspace?
  2. When is ${DEEPSEEK_API_KEY} resolved?
  3. Why should a preset specify both Provider and model?
  4. Why does a normal response not prove that the Tool Call path works?
  5. Why is interactive history not the same as long-term Memory?

Next step

Read Five entry points and their runtime boundaries.