Skip to main content

nao init

The nao init command sets up your context repository with all necessary files and structure. Run nao init
If nao_config.yaml already exists, nao init runs an update flow and lets you adjust existing configuration values instead of starting from scratch. nao init keeps the interactive setup to the essentials - project name, one database, one LLM, and one git repository. Everything else (extra databases and repos, Slack, Notion, MCP servers, skills, profiling) is configured afterwards by editing nao_config.yaml. 1. Project Name
The project name defaults to the current folder name - press Enter to accept it, or type a different name. 2. Database Connection (Optional)
If you say yes, you’ll be prompted for the connection details specific to your database type. The database is scaffolded with the columns and preview templates (plus ai_summary when you configure an LLM); profiling and query_history are written as commented-out options you can enable later. See Databases for the full template and connection reference. 3. LLM API Key (Optional)
If you use the Ollama provider you can skip the API key, as Ollama does not require one. For an OpenAI-compatible endpoint, nao asks for a name and a base URL, and the API key is optional. To offer several providers or models, add them to the llm.providers list in nao_config.yaml afterwards - see LLM providers and models. 4. Git Repository (Optional)
nao init sets up a single database, LLM, and repo. To add more, or to configure Slack, Notion, MCP servers, or skills, edit nao_config.yaml directly - re-running nao init on an existing project opens an update flow instead of starting over.
Non-interactive mode For CI pipelines or coding agents, run nao init without any prompts:
In --yes mode:
  • If nao_config.yaml already exists, it is reused as-is and only the folder structure is scaffolded.
  • If no config exists, a minimal one is created with the project name (from --name or the current directory name).
  • Databases, LLM, and integrations are not configured. Edit nao_config.yaml afterward or use the setup-context skill.
What Gets Created After running nao init, you’ll have a folder with the architecture of your context:
MCP servers are configured via the agent/mcps/mcp.json file, while skills are defined as markdown files in the agent/skills/ folder. Both are part of your project context and are discovered automatically by the agent.

nao sync

Once initialized, populate your context with actual content:
This will:
  • Connect to configured databases and pull schemas
  • Clone configured repositories
  • Sync configured Notion pages into markdown files under docs/notion/
  • Generate structured context files
  • Index content for your agent

nao debug

Verify your configuration:
This checks:
  • Configuration file syntax
  • Database connectivity
  • LLM API access
  • Environment variables
  • File permissions
It tests every database declared in nao_config.yaml, then tests each LLM provider listed under llm.providers. Connection checks are available for OpenAI, Anthropic, Gemini, Mistral, OpenRouter, Ollama, AWS Bedrock, and Google Vertex.
  • Ollama: lists the models available on the local Ollama instance.
  • AWS Bedrock: reports the resolved region, then lists foundation models using your aws_profile / AWS_PROFILE credentials. If a bearer token is set as the API key, nao reports it as configured without listing models.
  • Google Vertex: reports the resolved gcp_project and gcp_location and the credential source it picked up (service account JSON, key file, or application default credentials). It fails if gcp_project is not set.
If you set base_url on a provider to point at an OpenAI-compatible proxy such as LiteLLM, nao debug uses that base URL for the connectivity test instead of the provider default, so the check reflects the endpoint your agent actually calls. This applies to the openai, anthropic, and openrouter providers.

nao_config.yaml

The nao_config.yaml file is the central configuration for your analytics agent. You can always edit it and re-launch a sync with this configuration. Basic Structure
Every key is documented in the configuration reference. The llm block is detailed in LLM providers and models below, the semantic_layer block in Semantic Layer, and the test block in Evaluation. Environment Variables
Never commit sensitive credentials to Git! Always use environment variables for secrets.
Store sensitive values in environment variables (examples for different providers and warehouses):
Reference them in your config:
Warehouse Credentials For Warehouse credentials, you can use either method: Method 1: credentials_path (local development)
Method 2: credentials_json (cloud deployments)
Use credentials_json for cloud deployments (Cloud Run, GitHub Actions, etc.) where you store the full JSON content in an environment variable or secret manager. Use credentials_path for local development with credential files.
When using credentials_json, the environment variable must contain the entire JSON content of your service account key file, not just the path.

LLM providers and models

The llm block holds a list of providers under providers, and each provider lists the models it exposes. Use it to offer your users a choice of models, to expose models nao doesn’t know about (a proxy alias, a fine-tune, a model released after your nao version), and to price each of them.
A provider can appear only once, and only one model per provider can be the default. Leave models out to expose the provider’s built-in model list, which is what nao init writes. Every provider you declare is picked up by nao chat, nao debug and nao test. The chat server reads the block directly, so models, display names, inference settings and prices reach the app without any extra environment variable.
Providers declared in nao_config.yaml show up in the admin UI under Settings -> Agent -> Models, badged nao_config.yaml. Editing one there saves an override in the database that keeps winning over the file until you delete it, so the file remains the durable source of truth. Resolution order per provider is admin UI -> nao_config.yaml -> environment variables. See Choose LLM models.

Provider credentials

AWS Bedrock with a bearer token:
AWS Bedrock with IAM credentials:
Bedrock also accepts aws_profile to use a named AWS CLI profile, such as an SSO one, instead of inline keys. Google Vertex AI, authenticating with Application Default Credentials, an inline service account or a key file:

OpenRouter

OpenRouter routes a single API key to models from many vendors, which is the quickest way to expose a model nao doesn’t ship with:
Model IDs are OpenRouter slugs in vendor/model form - copy them from the model list exactly as shown, including the vendor prefix. Leave models out to expose OpenRouter’s built-in list instead. If you omit api_key, nao falls back to the OPENROUTER_API_KEY environment variable. base_url (or OPENROUTER_BASE_URL) overrides the endpoint, for example to reach OpenRouter through a proxy. Two things are worth adding once the provider works:
nao’s built-in price table doesn’t cover every OpenRouter slug, so declare costs on models you route through it - otherwise their calls are missing from the usage dashboard, budgets and nao test cost column. OpenRouter publishes the per-token prices on each model page; the values above are an example, not a quote. Run nao debug after editing the file to check the key and endpoint before starting a chat.

Requesty

Requesty is another model router. Like OpenRouter it fronts many vendors behind one API key and uses vendor/model ids, so the setup is the same:
Model IDs are Requesty slugs in vendor/model form. If you omit api_key, nao falls back to the REQUESTY_API_KEY environment variable, and base_url (or REQUESTY_BASE_URL) overrides the default endpoint (https://router.requesty.ai/v1). Leave models out to expose the built-in list (openai/gpt-4o-mini, deepseek/deepseek-chat, anthropic/claude-haiku-4-5, anthropic/claude-sonnet-4-5). As with any router, nao has no price for slugs outside its built-in table, so declare costs on the models you use to keep cost tracking accurate.

Meta (Muse)

The meta provider (shown as Meta in the UI) connects to Meta’s Muse models through their OpenAI-compatible API:
If you omit api_key, nao falls back to the META_API_KEY environment variable, and base_url (or META_BASE_URL) overrides the default endpoint (https://api.meta.ai/v1). Leave models out to expose the built-in list: muse-spark-1.3 is also the default model for ai_summary, memory, and chat summaries on this provider. Muse models always reason: the reasoning effort goes from minimal to max, and off sends minimal rather than disabling reasoning. Custom Muse model ids stop at high.

OpenAI-compatible proxy (LiteLLM)

To route the agent through an LLM proxy such as LiteLLM, keep the underlying provider and add base_url pointing at the proxy endpoint:
base_url is supported on the openai, anthropic, and openrouter providers. nao debug runs its connectivity check against this base URL, so the test reflects the endpoint your agent actually calls. Because a proxy exposes model IDs nao has no price for, list them under models with their costs to keep cost tracking accurate.

Model costs

nao ships a price table for the models it knows and computes the cost of every call from it. A costs block on a model overrides that table token type by token type:
All four fields are optional and expressed in US dollars per million tokens; the ones you leave out fall back to nao’s table. These prices feed the usage dashboard, the budgets, and the cost column of nao test.

Migrating an older config

Before multiple providers were supported, the llm block declared a single provider inline:
That shape still loads β€” nao reads it as a one-entry providers list β€” but it prints a deprecation warning and cannot express several providers or per-model costs. Rewrite it with:
The command only touches the llm block and rewrites it as text, so comments and {{ env('...') }} references survive untouched.
llm.meta.costs is deprecated. Prices declared there apply to every model, which gets misleading as soon as you run more than one. Move them to the costs of the matching model.

nao sync

The nao sync command populates your context folder with content from configured sources.
You can limit a sync to specific providers with --provider (or -p).
Supported provider values are:
  • databases (aliases: db, dbs, database)
  • repositories (aliases: repo, repos, repository)
  • notion
You can also target one configured connection by using provider:connection-name:
Use this when you want to refresh only part of your context instead of running every configured sync provider. Sync specific schemas or tables with --select By default, if you narrow a database sync to a subset of tables, nao sync removes any previously-synced table or schema that was not part of the run. Use --select (or -s) to refresh only a selection without deleting the rest of your synced context.
Behavior:
  • A pattern with no dot (analytics) selects every table in that schema (analytics.*).
  • A pattern with a dot (analytics.orders) selects a specific table; glob wildcards are supported (staging.dim_*).
  • Selection is applied on top of the existing include / exclude config in nao_config.yaml: it narrows further, never widens.
  • When --select is passed, stale-path cleanup is skipped, so tables and schemas outside the selection are preserved.
  • Tables and Snowflake semantic views both respect the selection.
Use this to refresh one table on a large warehouse without re-syncing everything. Run the sync in parallel By default nao sync uses a single worker thread. Speed up large syncs with -t / --threads:
This overrides the threads value in nao_config.yaml (which itself defaults to 1). The value must be 1 or greater. What Gets Synced When you run nao sync, the following happens: 1. Database Schemas For each database in your nao_config.yaml:
  • Connect to the database
  • Extract schema information (tables, columns, data types)
  • Generate context files in databases/ folder
  • Create structured files for each table:
    • columns.md - Column definitions and types, table description, row count, and partitioning
    • preview.md - Sample data preview
    • profiling.md - Data profiling information
    • annotations.md - Your own notes for the agent, created once and never overwritten
Example structure after sync:
Who owns each file Every file written during a sync starts with a frontmatter header declaring its origin, so you can tell what a re-sync will overwrite:
  • type: generated - written by the agent on every sync. Edits are lost on the next run.
  • type: manual - written once and left alone afterwards. Safe to edit.
annotations.md is the manual file: nao sync creates it per table folder with only the header, and skips it on later runs if it already exists. Everything else under databases/ is regenerated. See Databases for details. 2. Repositories For each repository in your configuration:
  • Clone or pull the latest code
  • Extract relevant files from specified paths
  • Index content for the agent
  • Store in docs/ folder
3. Indexing After syncing:
  • Content is indexed for fast semantic search
  • Embeddings are created for relevant context retrieval
  • Agent can access all synced information
To keep your context fresh automatically, schedule nao sync with GitHub Actions - see Git Repository Setup. Next Steps

Git Repository Setup

Version your context and automate nao sync with GitHub Actions

Context Principles

Learn how to optimize your context for reliability, speed, and cost