# Jiva Configuration Guide

## Overview

Jiva supports any OpenAI-compatible API provider including Krutrim, Groq, Sarvam, OpenAI, Ollama, and others. The configuration system is fully provider-agnostic — all provider-specific behaviour (tool format, reasoning effort strategy, token budgets) is driven by configuration flags, not hardcoded logic.

## Configuration Location

Your configuration is stored at:
- macOS/Linux: `~/.config/jiva-nodejs/config.json`
- Windows: `%APPDATA%\jiva-nodejs\config.json`

You can view the exact path and current configuration with:
```bash
jiva config --show
```

This displays:
```
∞ Jiva Configuration

Configuration source: /Users/username/.config/jiva-nodejs/config.json

Reasoning Model:
  Endpoint: https://api.groq.com/openai/v1/chat/completions
  Model: openai/gpt-oss-120b
  Harmony Format: No

MCP Servers:
  filesystem: enabled
  playwright: enabled
```

## Interactive Configuration

### First-Time Setup

```bash
jiva setup
```

This runs the interactive setup wizard. It starts by asking you to choose a provider:

```
? Select your LLM provider:
  ❯ Krutrim
    Groq
    Sarvam
    OpenAI-Compatible (custom endpoint)
```

Selecting a named provider automatically fills in the API endpoint, default model name, tool format, and reasoning effort strategy. You only need to supply your API key (and optionally override the model name).

For **OpenAI-Compatible**, you are prompted to enter the endpoint and model name manually.

The wizard then (optionally) configures a **multimodal model** for image understanding. Note: Sarvam does not currently offer a multimodal model — this step is skipped automatically when Sarvam is selected for reasoning.

**API key deduplication:** If you select the same provider for both the reasoning and multimodal models, the wizard asks for the key only once.

### Updating Configuration

```bash
jiva config
```

Choose what to update:
- Reasoning Model
- Multimodal Model
- MCP Servers
- Debug Mode
- View Configuration
- Reset All

## Tool Format Configuration

Different providers use different formats for tool calling:

### Harmony Format (Krutrim only)
- Used by: Krutrim Cloud with `gpt-oss-120b`
- Tools embedded in developer message as TypeScript-like signatures
- Response format: `<|call|>tool_name(args)<|return|>`
- **Set**: `useHarmonyFormat: true`

### Standard OpenAI Format (all other providers)
- Used by: Groq, Sarvam, OpenAI, Ollama, and most other providers
- Tools sent as separate `tools` array in the request body
- Response format: Standard `tool_calls` structure
- **Set**: `useHarmonyFormat: false` (or omit — this is the default)

### Provider Presets

The setup wizard automatically sets the correct format based on provider selection — no manual configuration needed:

| Provider | `useHarmonyFormat` |
|----------|--------------------|
| Krutrim | `true` |
| Groq | `false` |
| Sarvam | `false` |
| OpenAI-Compatible | `false` |

## Reasoning Effort Strategy

Controls how reasoning effort (`low` / `medium` / `high`) is communicated to the model:

| Strategy | Behaviour | Recommended for |
|----------|-----------|-----------------|
| `api_param` | Sent as `reasoning_effort` request field | Groq, Sarvam |
| `system_prompt` | Injected as leading system message: `"Reasoning: <level>"` | Krutrim gpt-oss-120b |
| `both` | Both of the above | Unknown / custom providers |

The setup wizard sets this automatically. You can override it in the config file:

```json
{
  "models": {
    "reasoning": {
      "reasoningEffortStrategy": "api_param"
    }
  }
}
```

## Provider Examples

### Krutrim Cloud

```json
{
  "models": {
    "reasoning": {
      "endpoint": "https://cloud.olakrutrim.com/v1/chat/completions",
      "apiKey": "your-krutrim-api-key",
      "model": "gpt-oss-120b",
      "type": "reasoning",
      "useHarmonyFormat": true,
      "reasoningEffortStrategy": "system_prompt"
    }
  }
}
```

### Groq

```json
{
  "models": {
    "reasoning": {
      "endpoint": "https://api.groq.com/openai/v1/chat/completions",
      "apiKey": "your-groq-api-key",
      "model": "openai/gpt-oss-120b",
      "type": "reasoning",
      "reasoningEffortStrategy": "api_param"
    }
  }
}
```

### Sarvam

Sarvam-105B is a reasoning model that internally performs a chain-of-thought pass before producing output. Set `defaultMaxTokens` to at least `8192` to give the model sufficient token budget for both reasoning and output.

```json
{
  "models": {
    "reasoning": {
      "endpoint": "https://api.sarvam.ai/v1/chat/completions",
      "apiKey": "your-sarvam-api-key",
      "model": "sarvam-105b",
      "type": "reasoning",
      "useHarmonyFormat": false,
      "reasoningEffortStrategy": "api_param",
      "defaultMaxTokens": 8192
    }
  }
}
```

Sarvam does not offer a multimodal model. Do not configure a `multimodal` block when using Sarvam as your sole provider.

### OpenAI

```json
{
  "models": {
    "reasoning": {
      "endpoint": "https://api.openai.com/v1/chat/completions",
      "apiKey": "sk-...",
      "model": "gpt-4o",
      "type": "reasoning"
    }
  }
}
```

### Ollama (Local)

```json
{
  "models": {
    "reasoning": {
      "endpoint": "http://localhost:11434/v1/chat/completions",
      "apiKey": "not-needed",
      "model": "llama3.1",
      "type": "reasoning"
    }
  }
}
```

## Configuration Schema

### Full Configuration Structure

```typescript
{
  models: {
    reasoning: {
      name: string;              // "reasoning"
      endpoint: string;          // API endpoint URL
      apiKey: string;            // API key
      type: "reasoning";         // Fixed type
      model?: string;            // Model name/ID (preferred)
      defaultModel?: string;     // Alias for model (legacy)
      useHarmonyFormat?: boolean; // Krutrim gpt-oss-120b only; defaults to false
      reasoningEffortStrategy?: "api_param" | "system_prompt" | "both"; // defaults to "both"
      defaultReasoningEffort?: "low" | "medium" | "high";
      defaultMaxTokens?: number; // Required for Sarvam-105B (8192 recommended)
      includeReasoning?: boolean; // Request thinking tokens in response (Groq)
    };
    multimodal?: {
      name: string;              // "multimodal"
      endpoint: string;          // API endpoint URL
      apiKey: string;            // API key
      type: "multimodal";        // Fixed type
      model?: string;            // Model name/ID
      defaultModel?: string;     // Alias for model (legacy)
    };
  };
  mcpServers: {
    [serverName: string]: {
      command: string;           // Command to run
      args?: string[];           // Command arguments
      env?: Record<string, string>; // Environment variables
      enabled: boolean;          // Whether server is enabled
    };
  };
  debug: boolean;                // Enable debug logging
}
```

## MCP Servers Configuration

Jiva uses the Model Context Protocol (MCP) for tool integration.

### Default Servers

The setup wizard automatically configures:
- **filesystem** - File operations (read, write, search, etc.)
- **playwright** (optional) - Browser automation

### Managing Servers

```bash
jiva config → MCP Servers
```

Options:
- **List Servers** - View all configured servers and their status
- **Add Server** - Add a new MCP server
- **Remove Server** - Remove an existing server

### Example: Adding a Custom Server

```bash
jiva config
→ MCP Servers
→ Add Server

Server name: github
Command: npx
Arguments (space-separated): -y @modelcontextprotocol/server-github
```

### Disabling a Server

Edit the config file and set `enabled: false`:

```json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["-y", "@playwright/mcp"],
      "enabled": false
    }
  }
}
```

## Multimodal Configuration

For image understanding, configure a multimodal model:

```json
{
  "models": {
    "multimodal": {
      "endpoint": "https://cloud.olakrutrim.com/v1/chat/completions",
      "apiKey": "your-api-key",
      "model": "Llama-4-Maverick-17B-128E-Instruct",
      "type": "multimodal"
    }
  }
}
```

When multimodal is configured, Jiva will:
1. Use multimodal model to describe images
2. Pass descriptions to reasoning model for analysis
3. Support image URLs in user messages

## Debug Mode

Enable detailed logging:

```bash
jiva config → Debug Mode → Yes
```

Or via command line:
```bash
jiva chat --debug
```

Debug mode logs:
- API requests and responses
- Tool call details
- Message formatting
- Token usage
- Error details

## Environment Variables

You can override config with environment variables:

```bash
# Override reasoning model endpoint
export JIVA_REASONING_ENDPOINT="https://api.groq.com/openai/v1/chat/completions"

# Override API key
export JIVA_API_KEY="your-api-key"

# Enable debug mode
export JIVA_DEBUG=true
```

## Configuration Best Practices

### 1. Start with Setup Wizard
Always use `jiva setup` for first-time configuration. It provides smart defaults and validates your inputs.

### 2. Let Smart Detection Work
The wizard detects the correct tool format based on your model name. Accept the recommendation unless you know it's wrong.

### 3. Test with Simple Commands
After configuring, test with:
```bash
jiva run "Say hello"
```

### 4. Use Debug Mode for Troubleshooting
If something isn't working:
```bash
jiva chat --debug
```

### 5. Keep API Keys Secure
- Never commit config files with API keys to version control
- Use environment variables in CI/CD environments
- Rotate keys regularly

## Troubleshooting

### "Tool choice is none, but model called a tool"

**Cause**: Wrong tool format setting for your provider.

**Solution**:
```bash
jiva config → Reasoning Model
# When prompted for tool format:
# - Krutrim gpt-oss-120b: Yes (Harmony)
# - Groq/OpenAI/Others: No (Standard)
```

### "403 Access Denied" or WAF Errors

**Cause**: Request payload too large, often from too many MCP tools.

**Solutions**:
1. Disable unused MCP servers:
   ```bash
   jiva config → MCP Servers → Remove Server
   ```

2. Reduce tool descriptions in custom servers

3. Use selective tool loading

### Configuration Not Persisting

**Check**:
1. File permissions on config directory
2. Disk space
3. Try resetting: `jiva config → Reset All`

### Model Not Found

**Verify**:
1. Model name is correct for your provider
2. API key has access to that model
3. Endpoint URL is correct

## Migration Guide

### Switching Providers

The easiest way to switch providers is to re-run the setup wizard:

```bash
jiva setup
```

Select your new provider and the wizard fills in endpoint, model, and format settings automatically.

### From Krutrim to Groq (manual)

1. Run `jiva config → Reasoning Model`
2. Update endpoint: `https://api.groq.com/openai/v1/chat/completions`
3. Update API key: Your Groq API key
4. Update model: `openai/gpt-oss-120b` (or another Groq model)
5. Set tool format: **No** (Standard OpenAI format)
6. Set `reasoningEffortStrategy: "api_param"` in config file

### From Krutrim to Sarvam (manual)

1. Run `jiva config → Reasoning Model`
2. Update endpoint: `https://api.sarvam.ai/v1/chat/completions`
3. Update API key: Your Sarvam API key
4. Update model: `sarvam-105b`
5. Set tool format: **No** (Standard)
6. Add `"reasoningEffortStrategy": "api_param"` and `"defaultMaxTokens": 8192` to the reasoning config in `config.json`

### From OpenAI to Local Ollama

1. Install and start Ollama
2. Pull a model: `ollama pull llama3.1`
3. Run `jiva config → Reasoning Model`
4. Update endpoint: `http://localhost:11434/v1/chat/completions`
5. API key: Use any value (not validated locally)
6. Model: `llama3.1`
7. Tool format: **No** (Standard)

## Advanced Configuration

### Custom Model Providers

Jiva works with any OpenAI-compatible API. Requirements:
- POST endpoint accepting OpenAI chat completion format
- Standard message roles: `system`, `user`, `assistant`, `tool`
- Optional: Tool calling support (standard OpenAI format)

## Custom Configuration Files

In addition to the default configuration stored in `~/.config/jiva-nodejs/`, you can provide custom configuration files for different projects or environments.

### Using Custom Config

Use the `--config` flag to specify a configuration file:

```bash
# Start chat with custom config
jiva chat --config ./my-project-config.json

# Run with custom config
jiva run "analyze this code" --config ./config/production.json

# Works with all options
jiva chat --config ./team-config.json --workspace ./src --directive ./jiva-directive.md
```

### Config File Format

The custom config file uses the same format as the default configuration:

```json
{
  "models": {
    "reasoning": {
      "name": "reasoning",
      "endpoint": "https://cloud.olakrutrim.com/v1/chat/completions",
      "apiKey": "YOUR_API_KEY_HERE",
      "type": "reasoning",
      "defaultModel": "gpt-oss-120b",
      "useHarmonyFormat": true
    },
    "multimodal": {
      "name": "multimodal",
      "endpoint": "https://cloud.olakrutrim.com/v1/chat/completions",
      "apiKey": "YOUR_API_KEY_HERE",
      "type": "multimodal",
      "defaultModel": "Llama-4-Maverick",
      "useHarmonyFormat": false
    }
  },
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users"],
      "enabled": true
    },
    "brave-search": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-brave-search"],
      "env": {
        "BRAVE_API_KEY": "YOUR_API_KEY"
      },
      "enabled": false
    }
  },
  "workspace": {
    "defaultDirectivePath": "./jiva-directive.md"
  },
  "debug": false
}
```

See [examples/jiva-config.example.json](../examples/jiva-config.example.json) for a complete template.

### Use Cases for Custom Config Files

**1. Project-Specific Configuration**
```bash
# Each project can have its own config
cd ~/projects/web-app
jiva chat --config ./jiva-config.json

cd ~/projects/data-analysis
jiva chat --config ./jiva-config.json
```

**2. Environment-Based Config**
```bash
# Different configs for dev/staging/production
jiva run "deploy" --config ./config/dev.json
jiva run "deploy" --config ./config/prod.json
```

**3. Team Configuration Sharing**
```bash
# Check config into Git (without API keys!)
git add team-jiva-config.json
git commit -m "Add team Jiva configuration"

# Team members use the shared config
jiva chat --config ./team-jiva-config.json
```

**4. Testing Different Models**
```bash
# Compare different model providers
jiva run "test query" --config ./config/groq.json
jiva run "test query" --config ./config/sarvam.json
jiva run "test query" --config ./config/krutrim.json
```

### Best Practices

**Don't commit API keys!** Use environment variables or `.env` files:

```json
{
  "models": {
    "reasoning": {
      "apiKey": "${JIVA_API_KEY}",
      "endpoint": "${JIVA_ENDPOINT}",
      ...
    }
  }
}
```

Then load from environment:
```bash
export JIVA_API_KEY="your-key"
jiva chat --config ./project-config.json
```

**Export your current config** to create a template:
```bash
# View current config and path
jiva config --show

# Copy to project (manually copy the values)
cp ~/.config/jiva-nodejs/config.json ./my-config-template.json

# Remove sensitive data
nano my-config-template.json
```

## Code Mode Configuration

Code mode activates a single-loop `CodeAgent` optimized for software engineering tasks. It replaces the Manager/Worker/Client chain with direct tool execution and optional LSP integration.

### Activating Code Mode

**Via CLI flag (per-session):**
```bash
jiva chat --code
jiva run "refactor auth.ts" --code
jiva chat --code --no-lsp    # disable LSP servers
```

**Via config file (persistent):**
```json
{
  "codeMode": {
    "enabled": true,
    "lsp": { "enabled": true },
    "maxIterations": 50
  }
}
```

**Via environment variable (cloud/container deployments):**
```bash
JIVA_CODE_MODE=true          # activate code mode
JIVA_CODE_LSP=false          # optional: disable LSP
```

### LSP Language Servers

Code mode optionally starts language servers (from PATH) after each file edit to surface compiler errors in the tool result. Servers are started lazily and silently skipped if not installed.

```bash
# TypeScript / JavaScript
npm install -g typescript-language-server typescript

# Python
pip install python-lsp-server

# Go
go install golang.org/x/tools/gopls@latest

# Rust
rustup component add rust-analyzer
```

For the full reference see [Code Mode Architecture](../architecture/CODE_MODE.md).

---

## Cloud Run Configuration

For Cloud Run deployments, configuration is loaded dynamically from GCS using a per-session scoped `StorageProvider`. See [CLOUD_RUN_DEPLOYMENT.md](../deployment/CLOUD_RUN_DEPLOYMENT.md) for full deployment details.

### Configuration storage path

All per-tenant configuration lives in a **single JSON file** per tenant:

```
gs://your-bucket/{tenantId}/config.json
```

The file combines model config and MCP server list — there is no separate `models.json` / `mcpServers.json` split.

### What SessionManager does on session creation

1. Calls `storageProvider.createSessionScoped({ tenantId, sessionId })` to get an isolated provider instance with a fixed, immutable GCS path prefix — concurrent tenants can never corrupt each other's paths.
2. Reads `{tenantId}/config.json` from GCS (cache is invalidated per-tenant on each new session).
3. Falls back to server-level environment variables (`JIVA_MODEL_*`, etc.) if no per-tenant config file is found.
4. Saves the resolved config back to `{tenantId}/config.json` so subsequent sessions inherit it.

### Uploading per-tenant config

```bash
cat > config.json <<'EOF'
{
  "models": {
    "reasoning": {
      "endpoint": "https://api.groq.com/openai/v1/chat/completions",
      "apiKey": "gsk_...",
      "model": "openai/gpt-oss-120b"
    }
  },
  "mcpServers": [
    { "name": "tavily-mcp", "command": "npx", "args": ["-y", "tavily-mcp@latest"], "env": { "TAVILY_API_KEY": "tvly-..." } }
  ]
}
EOF
gsutil cp config.json gs://your-bucket/my-tenant/config.json
```

### Programmatic Configuration

For advanced use cases, configure via Node.js:

```typescript
import { configManager } from 'jiva-core';

configManager.setReasoningModel({
  name: 'reasoning',
  endpoint: 'https://api.example.com/v1/chat/completions',
  apiKey: process.env.API_KEY,
  type: 'reasoning',
  defaultModel: 'my-model',
  useHarmonyFormat: false,
});
```

See `examples/programmatic-usage.ts` for more details.

## Getting Help

If you're stuck:

1. Check the [Troubleshooting Guide](TROUBLESHOOTING.md)
2. Run with debug mode: `jiva chat --debug`
3. View your config: `jiva config → View Configuration`
4. Open an issue on GitHub with debug logs

## Related Documentation

- [Quick Start Guide](QUICKSTART.md)
- [Troubleshooting](TROUBLESHOOTING.md)
- [MCP Servers](https://github.com/modelcontextprotocol/servers)
- [Programmatic Usage](../examples/programmatic-usage.ts)
