sovara 0.3.3__tar.gz → 0.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sovara-0.3.3 → sovara-0.3.4}/PKG-INFO +5 -1
- {sovara-0.3.3 → sovara-0.3.4}/README.md +2 -0
- {sovara-0.3.3 → sovara-0.3.4}/pyproject.toml +6 -2
- sovara-0.3.4/src/sovara/assets/sovara/SKILL.md +68 -0
- sovara-0.3.4/src/sovara/assets/sovara/enterprise-azure.md +496 -0
- sovara-0.3.4/src/sovara/assets/sovara/enterprise-palantir.md +82 -0
- sovara-0.3.4/src/sovara/assets/sovara/evals/evals.json +55 -0
- sovara-0.3.4/src/sovara/assets/sovara/evals/trigger_queries.json +126 -0
- sovara-0.3.4/src/sovara/assets/sovara/install-desktop-app.md +82 -0
- sovara-0.3.4/src/sovara/assets/sovara/install-python-sdk.md +83 -0
- sovara-0.3.4/src/sovara/assets/sovara/install-ts-sdk.md +103 -0
- sovara-0.3.4/src/sovara/assets/sovara/optimizing-agents.md +217 -0
- sovara-0.3.4/src/sovara/assets/sovara/references/cli-reference.md +191 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/so_tool.py +114 -189
- sovara-0.3.4/src/sovara/common/agent_credentials.py +90 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/config.py +113 -12
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/constants.py +28 -42
- sovara-0.3.4/src/sovara/common/db_credentials.py +85 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/node_naming.py +13 -2
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/utils.py +33 -2
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/agent_runner.py +46 -87
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parser.py +2 -2
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/claude_sdk_patch.py +10 -62
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/priors.py +0 -3
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/public.py +32 -52
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/record_entrypoint.py +0 -4
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/runtime_client.py +2 -45
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/PKG-INFO +5 -1
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/SOURCES.txt +12 -2
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/requires.txt +1 -0
- sovara-0.3.3/src/sovara/assets/SKILL.md +0 -908
- sovara-0.3.3/src/sovara/common/user.py +0 -89
- {sovara-0.3.3 → sovara-0.3.4}/setup.cfg +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/assets/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/sovara.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/annotations.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/code_version.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/code_version_remote_cases.json +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/custom_metrics.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/edit_io_exclude_patterns.json +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/endpoint_patterns.json +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/lifecycle.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/log_redaction.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/logger.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/payload_display.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/priors_block.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/priors_block_guidance.json +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/project.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/run_logs.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/sse_utils.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/to_show_filters.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/context_manager.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/aiohttp_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/claude_code_messages_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/httpx_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/mcp_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/requests_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/sse_utils.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/urllib3_api_parser.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/apply_monkey_patches.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/async_streaming.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/endpoint_whitelist.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/__init__.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/adk_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/aiohttp_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/httpx_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/langchain_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/mcp_patches.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/openai_agents_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/requests_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/urllib3_patch.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patching_utils.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/to_show_filters.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/tool_trace_utils.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/request_mutation.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/run_log_capture.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/trace.py +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/dependency_links.txt +0 -0
- {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sovara
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: Python SDK for Sovara agent observability and runtime instrumentation
|
|
5
|
+
Project-URL: Documentation, https://docs.sovara-labs.com
|
|
5
6
|
Requires-Python: >=3.10
|
|
6
7
|
Description-Content-Type: text/markdown
|
|
7
8
|
Requires-Dist: dill
|
|
@@ -9,6 +10,7 @@ Requires-Dist: flatten_dict
|
|
|
9
10
|
Requires-Dist: flatten_json
|
|
10
11
|
Requires-Dist: httpx
|
|
11
12
|
Requires-Dist: jsonpickle>=4.1.1
|
|
13
|
+
Requires-Dist: keyring>=25.0.0
|
|
12
14
|
Requires-Dist: pydantic
|
|
13
15
|
Requires-Dist: pyyaml
|
|
14
16
|
Provides-Extra: examples
|
|
@@ -47,3 +49,5 @@ with sovara.run("support-agent"):
|
|
|
47
49
|
The terminal command is distributed separately as the native Sovara CLI. Install
|
|
48
50
|
that CLI for commands such as `sovara record`, `sovara status`, and
|
|
49
51
|
`sovara probe`.
|
|
52
|
+
|
|
53
|
+
Documentation: https://docs.sovara-labs.com
|
|
@@ -3,7 +3,7 @@ requires = ["setuptools"]
|
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[tool.setuptools.package-data]
|
|
6
|
-
"sovara.assets" = ["
|
|
6
|
+
"sovara.assets" = ["sovara/*.md", "sovara/references/*.md", "sovara/evals/*.json"]
|
|
7
7
|
"sovara.common" = ["*.json"]
|
|
8
8
|
|
|
9
9
|
[tool.setuptools]
|
|
@@ -15,7 +15,7 @@ include = ["sovara*"]
|
|
|
15
15
|
|
|
16
16
|
[project]
|
|
17
17
|
name = "sovara"
|
|
18
|
-
version = "0.3.
|
|
18
|
+
version = "0.3.4"
|
|
19
19
|
description = "Python SDK for Sovara agent observability and runtime instrumentation"
|
|
20
20
|
readme = "README.md"
|
|
21
21
|
requires-python = ">=3.10"
|
|
@@ -26,6 +26,7 @@ dependencies = [
|
|
|
26
26
|
"flatten_json",
|
|
27
27
|
"httpx",
|
|
28
28
|
"jsonpickle>=4.1.1",
|
|
29
|
+
"keyring>=25.0.0",
|
|
29
30
|
"pydantic",
|
|
30
31
|
"pyyaml",
|
|
31
32
|
]
|
|
@@ -38,3 +39,6 @@ examples = [
|
|
|
38
39
|
"google-genai",
|
|
39
40
|
"claude-agent-sdk",
|
|
40
41
|
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Documentation = "https://docs.sovara-labs.com"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sovara
|
|
3
|
+
description: >
|
|
4
|
+
Use when a user wants to debug, observe, optimize, or capture lessons
|
|
5
|
+
from a Python or TypeScript LLM agent — recording runs as dataflow
|
|
6
|
+
graphs of LLM and tool calls, inspecting which step produced a wrong
|
|
7
|
+
answer, comparing runs to find regressions, annotating failures, or
|
|
8
|
+
turning recurring lessons into priors that are injected back into
|
|
9
|
+
context at runtime. Also covers installing the Sovara desktop app,
|
|
10
|
+
SDK, or CLI, deploying `sovara-server` on Azure with Microsoft
|
|
11
|
+
Entra auth, or configuring Sovara for Palantir Foundry. Trigger even when the user does not say "Sovara" —
|
|
12
|
+
phrases like "my agent keeps giving wrong answers", "trace this LLM
|
|
13
|
+
call", "the agent regressed after my last change", "remember this
|
|
14
|
+
rule for next time", "inject domain knowledge into my agent at
|
|
15
|
+
runtime", or "set up observability for my agent" all apply. Do not
|
|
16
|
+
use for generic prompt engineering with no run inspection, generic
|
|
17
|
+
HTTP/SQL tracing unrelated to LLM agents, or Azure deployment
|
|
18
|
+
unrelated to `sovara-server`.
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# sovara
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
Sovara helps develop and maintain adaptable agentic systems by recording traces as dataflow graphs and injecting learned priors at runtime.
|
|
26
|
+
|
|
27
|
+
Core capabilities:
|
|
28
|
+
|
|
29
|
+
- **Integrated observability**: Record agent traces as dataflow graphs with zero code changes for supported Python workflows.
|
|
30
|
+
- **Priors**: Create, retrieve, validate, and inject reusable lessons into agent context.
|
|
31
|
+
- **SDK install guidance**: Install the desktop app, SDK/runner, CLI, and assistant skill.
|
|
32
|
+
- **Enterprise deploy guidance**: Stand up `sovara-server` on Azure with Microsoft Entra auth.
|
|
33
|
+
- **Palantir setup guidance**: Configure Sovara to use Palantir Foundry as the storage backend and embedding provider.
|
|
34
|
+
|
|
35
|
+
## Setup Gate
|
|
36
|
+
|
|
37
|
+
Run project setup checks only for workflows that execute Sovara against a project: recording, probing, logs, annotations, priors, or connecting an agent to a server. Skip this gate when the user only needs SDK/CLI installation guidance or enterprise deployment planning.
|
|
38
|
+
|
|
39
|
+
For project-scoped workflows:
|
|
40
|
+
|
|
41
|
+
1. Run `sovara status --path <script-or-project-dir>` before the first project command.
|
|
42
|
+
2. If setup is missing, run `sovara init --project-root <dir> --project-name "<name>"`.
|
|
43
|
+
3. In non-interactive shells, do not rely on prompts. Initialize first, or pass `--project-root`, `--project-name`, and `--project-description` directly to `sovara record`.
|
|
44
|
+
4. Use `sovara projects` when scope is ambiguous. Commands such as `sovara runs ...`, `sovara annotations ...`, and `sovara priors ...` accept `--project-id` / `--proj-id` with a full ID or unambiguous prefix.
|
|
45
|
+
5. Install or refresh this shared skill only when asked: `sovara install-skill [--level global|project] [--project-dir <dir>] [--target codex|claude|both]`.
|
|
46
|
+
|
|
47
|
+
## Task Routing
|
|
48
|
+
|
|
49
|
+
Read only the file that matches the user's task:
|
|
50
|
+
|
|
51
|
+
- **[optimizing-agents.md](optimizing-agents.md)**: Record, probe, annotate, and improve agent runs; create and manage priors. Use for day-to-day Sovara workflows.
|
|
52
|
+
- **[install-desktop-app.md](install-desktop-app.md)**: Shared OS-level install steps (desktop app, CLI, assistant skill). Load alongside the language-specific install file below.
|
|
53
|
+
- **[install-python-sdk.md](install-python-sdk.md)**: Install the Python SDK (`sovara`) and instrument a Python agent. Pair with `install-desktop-app.md`.
|
|
54
|
+
- **[install-ts-sdk.md](install-ts-sdk.md)**: Install the TypeScript runner (`@sovara/runner`) and instrument a Node.js agent. Pair with `install-desktop-app.md`.
|
|
55
|
+
- **[enterprise-azure.md](enterprise-azure.md)**: Deploy `sovara-server` on Azure Container Apps with Microsoft Entra app registrations.
|
|
56
|
+
- **[enterprise-palantir.md](enterprise-palantir.md)**: Configure Sovara Server to use Palantir Foundry for ontology-backed storage and AIP embeddings.
|
|
57
|
+
|
|
58
|
+
If the task spans multiple files, read them in this order: install first, optimize second, enterprise/provider setup last. Apply only the sections that match the request.
|
|
59
|
+
|
|
60
|
+
## On-Demand References
|
|
61
|
+
|
|
62
|
+
- **[references/cli-reference.md](references/cli-reference.md)**: Load only when exact flags, command shapes, output schemas, or troubleshooting details are needed.
|
|
63
|
+
- **[evals/evals.json](evals/evals.json)**: Output evals — schema-compliant test cases for whether the loaded skill produces good agent behavior.
|
|
64
|
+
- **[evals/trigger_queries.json](evals/trigger_queries.json)**: Trigger evals — realistic prompts (with and without the word "Sovara") used to test whether the description fires correctly. Do not load when answering user requests; this file is for skill maintainers.
|
|
65
|
+
|
|
66
|
+
## Feedback
|
|
67
|
+
|
|
68
|
+
When a Sovara command should work but does not, propose posting in the Sovara Discord at [discord.gg/P6a93bWJ](https://discord.gg/P6a93bWJ) or emailing `support@sovara-labs.com`. Include the exact command, sanitized output, OS, Sovara CLI version, and whether the desktop app or enterprise server was running.
|
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: enterprise-azure
|
|
3
|
+
description: Deploy `sovara-server` on Microsoft Azure with Entra (OIDC/PKCE) authentication. Covers Azure Container Apps as the recommended default, plus Entra app registrations, database choices (MongoDB Atlas, PostgreSQL, SQLite), and connecting Remote desktop + agent projects. Use only for backend deployment work, not for local SDK install (see install-python-sdk.md / install-ts-sdk.md).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Enterprise deploy on Azure with Microsoft Entra
|
|
7
|
+
|
|
8
|
+
This sub-skill stands `sovara-server` up on Azure and protects it with Microsoft Entra. The recommended path is Azure Container Apps because it gives managed HTTPS ingress, container hosting, and secrets without operating a VM or Kubernetes cluster. The same Entra/server config applies to Azure App Service for Containers, Azure VMs, and AKS — only the hosting layer differs.
|
|
9
|
+
|
|
10
|
+
> The marketing source for this material lives at <https://docs.sovara-labs.com/enterprise/azure-entra-setup>. Use that page for the latest portal screenshots; this file is the agent-facing companion.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Architecture requirements
|
|
15
|
+
|
|
16
|
+
Whatever hosting model is chosen must provide:
|
|
17
|
+
|
|
18
|
+
- HTTPS endpoint reachable from user desktops.
|
|
19
|
+
- WebSocket support from the desktop app to the server.
|
|
20
|
+
- Reachability from agent machines that will report runs.
|
|
21
|
+
- Environment-variable or secret configuration for `sovara-server`.
|
|
22
|
+
- Reachable PostgreSQL or MongoDB database for Sovara state.
|
|
23
|
+
- Outbound HTTPS from the server to Microsoft identity endpoints (OIDC/JWKS).
|
|
24
|
+
|
|
25
|
+
Hosting options:
|
|
26
|
+
|
|
27
|
+
| Model | Use when | Notes |
|
|
28
|
+
| --- | --- | --- |
|
|
29
|
+
| Azure Container Apps | Simplest managed serverless container deployment | Recommended default |
|
|
30
|
+
| Azure App Service for Containers | Org standardizes on App Service | Same image, env vars, HTTPS, WebSocket |
|
|
31
|
+
| Azure VM | Direct OS / reverse-proxy control | Run image behind Nginx / Caddy / App Gateway |
|
|
32
|
+
| AKS | Org already operates Kubernetes | Standard Deployment, Service, Ingress, secrets |
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Prerequisites
|
|
37
|
+
|
|
38
|
+
- Azure subscription in the Entra tenant where users sign in.
|
|
39
|
+
- Permission to create app registrations in that tenant.
|
|
40
|
+
- Permission to create the selected Azure hosting resources.
|
|
41
|
+
- A reachable PostgreSQL or MongoDB database for Sovara state.
|
|
42
|
+
- Azure CLI installed and authenticated.
|
|
43
|
+
- The published Sovara Server container image tag from Sovara.
|
|
44
|
+
- The Remote desktop app build.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Variables
|
|
49
|
+
|
|
50
|
+
Choose names before running commands. Container App names must be lowercase, start with a letter, end with a letter or number, and be under 32 characters.
|
|
51
|
+
|
|
52
|
+
### Common (bash)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
export TENANT_ID="<tenant-guid>"
|
|
56
|
+
export SUBSCRIPTION_ID="<subscription-guid>"
|
|
57
|
+
export RESOURCE_GROUP="rg-sovara-enterprise"
|
|
58
|
+
export LOCATION="westeurope"
|
|
59
|
+
export CONTAINERAPPS_ENV="sovara-env"
|
|
60
|
+
export CONTAINER_APP_NAME="sovara-server"
|
|
61
|
+
export SERVER_API_APP_NAME="Sovara Server API"
|
|
62
|
+
export DESKTOP_APP_NAME="Sovara Desktop"
|
|
63
|
+
export SOVARA_IMAGE="<published-sovara-server-image>:<version>"
|
|
64
|
+
export REDIRECT_URI="http://localhost/auth/callback"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Database (pick exactly one)
|
|
68
|
+
|
|
69
|
+
MongoDB Atlas:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
export SOVARA_DB_BACKEND="mongodb"
|
|
73
|
+
export SOVARA_MONGODB_URI="mongodb+srv://<user>:<password>@<cluster>.mongodb.net/?retryWrites=true&w=majority"
|
|
74
|
+
export SOVARA_MONGODB_DB="sovara"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
PostgreSQL:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
export SOVARA_DB_BACKEND="postgresql"
|
|
81
|
+
export SOVARA_PG_DSN="postgresql://<user>:<password>@<host>:5432/sovara"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
SQLite is acceptable only for local dev or temporary validation deployments — not for shared production state.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Sign in and select the subscription
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
az login --tenant "$TENANT_ID"
|
|
92
|
+
az account set --subscription "$SUBSCRIPTION_ID"
|
|
93
|
+
az account show --query "{name:name,id:id,tenantId:tenantId,user:user.name}" -o table
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Confirm the printed `TenantId` and subscription match. If `az account set` says the subscription does not exist, re-login with the correct tenant.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Create the Entra app registrations
|
|
101
|
+
|
|
102
|
+
Sovara uses two app registrations:
|
|
103
|
+
|
|
104
|
+
- **Server API app** — represents `sovara-server`; exposes the `access_as_user` delegated scope.
|
|
105
|
+
- **Desktop app** — public client using PKCE and the loopback redirect URI `http://localhost/auth/callback`. No client secret.
|
|
106
|
+
|
|
107
|
+
### Server API app
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
SERVER_APP_ID=$(
|
|
111
|
+
az ad app create \
|
|
112
|
+
--display-name "$SERVER_API_APP_NAME" \
|
|
113
|
+
--sign-in-audience AzureADMyOrg \
|
|
114
|
+
--query appId \
|
|
115
|
+
-o tsv
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
SERVER_OBJECT_ID=$(az ad app show --id "$SERVER_APP_ID" --query id -o tsv)
|
|
119
|
+
|
|
120
|
+
az ad app update \
|
|
121
|
+
--id "$SERVER_APP_ID" \
|
|
122
|
+
--identifier-uris "api://$SERVER_APP_ID"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Expose the `access_as_user` scope
|
|
126
|
+
|
|
127
|
+
The scope ID must be a GUID. Patch the app manifest through Microsoft Graph:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
SCOPE_ID=$(uuidgen)
|
|
131
|
+
SCOPE_FILE=$(mktemp)
|
|
132
|
+
|
|
133
|
+
cat > "$SCOPE_FILE" <<EOF
|
|
134
|
+
{
|
|
135
|
+
"api": {
|
|
136
|
+
"requestedAccessTokenVersion": 2,
|
|
137
|
+
"oauth2PermissionScopes": [
|
|
138
|
+
{
|
|
139
|
+
"adminConsentDescription": "Allow Sovara Desktop to access Sovara Server as the signed-in user.",
|
|
140
|
+
"adminConsentDisplayName": "Access Sovara Server",
|
|
141
|
+
"id": "$SCOPE_ID",
|
|
142
|
+
"isEnabled": true,
|
|
143
|
+
"type": "User",
|
|
144
|
+
"userConsentDescription": "Allow Sovara Desktop to access Sovara Server as you.",
|
|
145
|
+
"userConsentDisplayName": "Access Sovara Server",
|
|
146
|
+
"value": "access_as_user"
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
EOF
|
|
152
|
+
|
|
153
|
+
az rest \
|
|
154
|
+
--method PATCH \
|
|
155
|
+
--uri "https://graph.microsoft.com/v1.0/applications/$SERVER_OBJECT_ID" \
|
|
156
|
+
--headers "Content-Type=application/json" \
|
|
157
|
+
--body "@$SCOPE_FILE"
|
|
158
|
+
|
|
159
|
+
SERVER_SCOPE_ID=$(
|
|
160
|
+
az ad app show \
|
|
161
|
+
--id "$SERVER_APP_ID" \
|
|
162
|
+
--query "api.oauth2PermissionScopes[?value=='access_as_user'].id | [0]" \
|
|
163
|
+
-o tsv
|
|
164
|
+
)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Desktop public client app
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
DESKTOP_APP_ID=$(
|
|
171
|
+
az ad app create \
|
|
172
|
+
--display-name "$DESKTOP_APP_NAME" \
|
|
173
|
+
--sign-in-audience AzureADMyOrg \
|
|
174
|
+
--is-fallback-public-client true \
|
|
175
|
+
--public-client-redirect-uris "$REDIRECT_URI" \
|
|
176
|
+
--query appId \
|
|
177
|
+
-o tsv
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
az ad app permission add \
|
|
181
|
+
--id "$DESKTOP_APP_ID" \
|
|
182
|
+
--api "$SERVER_APP_ID" \
|
|
183
|
+
--api-permissions "$SERVER_SCOPE_ID=Scope"
|
|
184
|
+
|
|
185
|
+
az ad sp create --id "$SERVER_APP_ID" >/dev/null
|
|
186
|
+
az ad sp create --id "$DESKTOP_APP_ID" >/dev/null
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Grant admin consent (if required)
|
|
190
|
+
|
|
191
|
+
For tenants that disallow user consent for delegated scopes:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
az ad app permission admin-consent --id "$DESKTOP_APP_ID"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Configure server auth env vars
|
|
200
|
+
|
|
201
|
+
Every hosting model must pass these env vars to `sovara-server`:
|
|
202
|
+
|
|
203
|
+
```text
|
|
204
|
+
SOVARA_AUTH_MODE=enterprise
|
|
205
|
+
SOVARA_ENTRA_TENANT_ID=<tenant-guid>
|
|
206
|
+
SOVARA_OIDC_ISSUER=https://login.microsoftonline.com/<tenant-guid>/v2.0
|
|
207
|
+
SOVARA_OIDC_AUDIENCE=<server-api-client-id>
|
|
208
|
+
SOVARA_OIDC_REQUIRED_SCOPE=access_as_user
|
|
209
|
+
SOVARA_DESKTOP_CLIENT_ID=<desktop-client-id>
|
|
210
|
+
SOVARA_DESKTOP_SCOPES=api://<server-api-client-id>/access_as_user
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
The container listens on `0.0.0.0:5959`. The Azure hosting layer terminates HTTPS and forwards to port `5959`.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Configure database and storage
|
|
218
|
+
|
|
219
|
+
Sovara persists projects, memberships, agent tokens, runs, annotations, priors, and model settings.
|
|
220
|
+
|
|
221
|
+
Configure the database at deployment time. Do **not** store the MongoDB URI or PostgreSQL DSN in the desktop app or in normal project settings.
|
|
222
|
+
|
|
223
|
+
### MongoDB Atlas (recommended first MongoDB path)
|
|
224
|
+
|
|
225
|
+
1. Create or select an Atlas project.
|
|
226
|
+
2. Create a cluster on **Microsoft Azure** in the same region as `sovara-server` if possible.
|
|
227
|
+
3. Create a database user with read/write on the `sovara` database.
|
|
228
|
+
4. In **Network Access**, allow the Sovara Server hosting environment. `0.0.0.0/0` is fine for validation; replace with Atlas private networking or a stable Azure outbound IP allowlist before production.
|
|
229
|
+
5. Copy the `mongodb+srv://...` connection string from the cluster **Connect** flow.
|
|
230
|
+
6. Substitute the real username/password into that string.
|
|
231
|
+
7. Set `SOVARA_MONGODB_URI` to the full string and `SOVARA_MONGODB_DB=sovara`.
|
|
232
|
+
|
|
233
|
+
For an existing Container App, update the secret and revision after rotating credentials:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
az containerapp secret set \
|
|
237
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
238
|
+
--name "$CONTAINER_APP_NAME" \
|
|
239
|
+
--secrets mongodb-uri="$SOVARA_MONGODB_URI"
|
|
240
|
+
|
|
241
|
+
az containerapp update \
|
|
242
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
243
|
+
--name "$CONTAINER_APP_NAME" \
|
|
244
|
+
--set-env-vars \
|
|
245
|
+
SOVARA_DB_BACKEND=mongodb \
|
|
246
|
+
SOVARA_MONGODB_URI=secretref:mongodb-uri \
|
|
247
|
+
SOVARA_MONGODB_DB="$SOVARA_MONGODB_DB"
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Updating a secret does not restart running revisions. After a rotation:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
ACTIVE_REVISION=$(
|
|
254
|
+
az containerapp revision list \
|
|
255
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
256
|
+
--name "$CONTAINER_APP_NAME" \
|
|
257
|
+
--query "[?properties.trafficWeight==\`100\`].name | [0]" \
|
|
258
|
+
-o tsv
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
az containerapp revision restart \
|
|
262
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
263
|
+
--name "$CONTAINER_APP_NAME" \
|
|
264
|
+
--revision "$ACTIVE_REVISION"
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### PostgreSQL
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
postgresql://<user>:<password>@<host>:5432/sovara
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
For a new Container App use `--secrets pg-dsn=...` in the create command and set `SOVARA_PG_DSN=secretref:pg-dsn`. For an existing app:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
az containerapp secret set \
|
|
277
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
278
|
+
--name "$CONTAINER_APP_NAME" \
|
|
279
|
+
--secrets pg-dsn="$SOVARA_PG_DSN"
|
|
280
|
+
|
|
281
|
+
az containerapp update \
|
|
282
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
283
|
+
--name "$CONTAINER_APP_NAME" \
|
|
284
|
+
--set-env-vars \
|
|
285
|
+
SOVARA_DB_BACKEND=postgresql \
|
|
286
|
+
SOVARA_PG_DSN=secretref:pg-dsn
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Deploy on Azure Container Apps
|
|
292
|
+
|
|
293
|
+
### Resource group + Container Apps environment
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
az extension add --name containerapp --upgrade
|
|
297
|
+
az provider register --namespace Microsoft.App
|
|
298
|
+
az provider register --namespace Microsoft.OperationalInsights
|
|
299
|
+
|
|
300
|
+
az group create \
|
|
301
|
+
--name "$RESOURCE_GROUP" \
|
|
302
|
+
--location "$LOCATION"
|
|
303
|
+
|
|
304
|
+
az containerapp env create \
|
|
305
|
+
--name "$CONTAINERAPPS_ENV" \
|
|
306
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
307
|
+
--location "$LOCATION"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Create the Container App
|
|
311
|
+
|
|
312
|
+
The published container listens on `5959`. Azure Container Apps gives it a public HTTPS endpoint:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
az containerapp create \
|
|
316
|
+
--name "$CONTAINER_APP_NAME" \
|
|
317
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
318
|
+
--environment "$CONTAINERAPPS_ENV" \
|
|
319
|
+
--image "$SOVARA_IMAGE" \
|
|
320
|
+
--ingress external \
|
|
321
|
+
--target-port 5959 \
|
|
322
|
+
--cpu 0.5 \
|
|
323
|
+
--memory 1.0Gi \
|
|
324
|
+
--min-replicas 1 \
|
|
325
|
+
--max-replicas 1 \
|
|
326
|
+
--secrets mongodb-uri="$SOVARA_MONGODB_URI" \
|
|
327
|
+
--env-vars \
|
|
328
|
+
SOVARA_AUTH_MODE=enterprise \
|
|
329
|
+
SOVARA_ENTRA_TENANT_ID="$TENANT_ID" \
|
|
330
|
+
SOVARA_OIDC_ISSUER="https://login.microsoftonline.com/$TENANT_ID/v2.0" \
|
|
331
|
+
SOVARA_OIDC_AUDIENCE="$SERVER_APP_ID" \
|
|
332
|
+
SOVARA_OIDC_REQUIRED_SCOPE=access_as_user \
|
|
333
|
+
SOVARA_DESKTOP_CLIENT_ID="$DESKTOP_APP_ID" \
|
|
334
|
+
SOVARA_DESKTOP_SCOPES="api://$SERVER_APP_ID/access_as_user" \
|
|
335
|
+
SOVARA_DB_BACKEND=mongodb \
|
|
336
|
+
SOVARA_MONGODB_URI=secretref:mongodb-uri \
|
|
337
|
+
SOVARA_MONGODB_DB="$SOVARA_MONGODB_DB"
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Get the server URL
|
|
341
|
+
|
|
342
|
+
```bash
|
|
343
|
+
SERVER_FQDN=$(
|
|
344
|
+
az containerapp show \
|
|
345
|
+
--name "$CONTAINER_APP_NAME" \
|
|
346
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
347
|
+
--query properties.configuration.ingress.fqdn \
|
|
348
|
+
-o tsv
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
SERVER_URL="https://$SERVER_FQDN"
|
|
352
|
+
echo "$SERVER_URL"
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
## Verify the server
|
|
356
|
+
|
|
357
|
+
```bash
|
|
358
|
+
curl -fsS "$SERVER_URL/health"
|
|
359
|
+
curl -fsS "$SERVER_URL/auth/config"
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
`/auth/config` should respond with:
|
|
363
|
+
|
|
364
|
+
```json
|
|
365
|
+
{
|
|
366
|
+
"auth_mode": "enterprise",
|
|
367
|
+
"provider": "entra",
|
|
368
|
+
"tenant_id": "<tenant-guid>",
|
|
369
|
+
"desktop_client_id": "<desktop-client-id>",
|
|
370
|
+
"scopes": ["api://<server-api-client-id>/access_as_user"],
|
|
371
|
+
"server_audience": "<server-api-client-id>"
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Connect the Remote desktop app
|
|
378
|
+
|
|
379
|
+
1. Open the Remote desktop app.
|
|
380
|
+
2. Enter the server HTTPS URL.
|
|
381
|
+
3. Click **Connect**.
|
|
382
|
+
4. Click **Sign in with Microsoft** and complete the browser login.
|
|
383
|
+
5. Confirm the desktop app shows the Entra profile.
|
|
384
|
+
6. Create a project — the creator becomes project admin.
|
|
385
|
+
|
|
386
|
+
---
|
|
387
|
+
|
|
388
|
+
## Connect an agent project
|
|
389
|
+
|
|
390
|
+
From the project's settings in the Remote desktop app, create an agent token. Then on the agent machine:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
sovara connect-agent \
|
|
394
|
+
--project-root /path/to/agent/project \
|
|
395
|
+
--server-url "$SERVER_URL" \
|
|
396
|
+
--project-id "<project-id>" \
|
|
397
|
+
--agent-token "<agent-token>"
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
After this one-time pairing, run the agent normally. Recorded runs appear in the project without the runner sending a user ID. For SDK install on the agent side, see [install-python-sdk.md](install-python-sdk.md) or [install-ts-sdk.md](install-ts-sdk.md).
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
## Access model
|
|
405
|
+
|
|
406
|
+
The Entra token only proves identity. Project access still comes from the Sovara database:
|
|
407
|
+
|
|
408
|
+
- Project creators become `admin`.
|
|
409
|
+
- Admins add members and create agent tokens.
|
|
410
|
+
- Editors and viewers cannot create agent tokens.
|
|
411
|
+
- Agent tokens can only write runs to their bound project.
|
|
412
|
+
|
|
413
|
+
Adding a member by email or user ID requires that the user has signed in at least once, so their Entra identity exists in Sovara. Directory-wide user search is not part of this setup because it requires Microsoft Graph permissions and admin consent.
|
|
414
|
+
|
|
415
|
+
---
|
|
416
|
+
|
|
417
|
+
## Troubleshooting
|
|
418
|
+
|
|
419
|
+
### `az account set` cannot find the subscription
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
az account list --query "[].{name:name,id:id,tenantId:tenantId,isDefault:isDefault}" -o table
|
|
423
|
+
az login --tenant "$TENANT_ID"
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
If the subscription still doesn't appear, the signed-in user lacks access to it in this tenant.
|
|
427
|
+
|
|
428
|
+
### App registration creation fails
|
|
429
|
+
|
|
430
|
+
The tenant likely blocks user app registrations. Ask an Entra admin to run those steps or grant the permission temporarily.
|
|
431
|
+
|
|
432
|
+
### Desktop login: redirect URI mismatch
|
|
433
|
+
|
|
434
|
+
- The Desktop app registration must be a public client/native app.
|
|
435
|
+
- It must have `http://localhost/auth/callback` as a redirect URI.
|
|
436
|
+
- `SOVARA_DESKTOP_CLIENT_ID` must be the Desktop app client ID, not the Server API app client ID.
|
|
437
|
+
|
|
438
|
+
### Desktop login: invalid audience or scope
|
|
439
|
+
|
|
440
|
+
- `SOVARA_OIDC_AUDIENCE` must equal the Server API app client ID.
|
|
441
|
+
- `SOVARA_DESKTOP_SCOPES` must equal `api://<server-api-client-id>/access_as_user`.
|
|
442
|
+
- The Desktop app must have the delegated `access_as_user` permission for the Server API app.
|
|
443
|
+
- If tenant policy requires it, admin consent must be granted.
|
|
444
|
+
|
|
445
|
+
### Desktop cannot load `/auth/config`
|
|
446
|
+
|
|
447
|
+
```bash
|
|
448
|
+
curl -v "$SERVER_URL/auth/config"
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
Check server URL, HTTPS ingress, container startup, and any network policy between desktop and Azure.
|
|
452
|
+
|
|
453
|
+
### MongoDB connection fails
|
|
454
|
+
|
|
455
|
+
Read the Container App logs first. Common causes:
|
|
456
|
+
|
|
457
|
+
- `Authentication failed` — bad Atlas user/password in `mongodb-uri`. Rotate and restart the active revision.
|
|
458
|
+
- `ServerSelectionTimeoutError` / connection timeout — Atlas IP access list or private networking blocks the outbound connection.
|
|
459
|
+
- `Cannot specify multiple hosts with directConnection=true` — the server image is too old for Atlas SRV URIs. Use a newer image.
|
|
460
|
+
|
|
461
|
+
For validation, `0.0.0.0/0` in the Atlas IP access list isolates DB/credentials issues; tighten before production.
|
|
462
|
+
|
|
463
|
+
### Inspect Container App logs
|
|
464
|
+
|
|
465
|
+
```bash
|
|
466
|
+
az containerapp logs show \
|
|
467
|
+
--name "$CONTAINER_APP_NAME" \
|
|
468
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
469
|
+
--follow
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Inspect Container App env vars
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
az containerapp show \
|
|
476
|
+
--name "$CONTAINER_APP_NAME" \
|
|
477
|
+
--resource-group "$RESOURCE_GROUP" \
|
|
478
|
+
--query "properties.template.containers[0].env" \
|
|
479
|
+
-o table
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## Clean up and retry
|
|
485
|
+
|
|
486
|
+
Only clean up Azure resources when the user explicitly asks to start over or remove the deployment. Treat this as destructive: first print the resolved resource group, subscription, tenant, Desktop app ID, and Server API app ID; then ask for explicit confirmation before running delete commands.
|
|
487
|
+
|
|
488
|
+
After confirmation, delete the resource group and both app registrations:
|
|
489
|
+
|
|
490
|
+
```bash
|
|
491
|
+
az group delete --name "$RESOURCE_GROUP" --yes
|
|
492
|
+
az ad app delete --id "$DESKTOP_APP_ID"
|
|
493
|
+
az ad app delete --id "$SERVER_APP_ID"
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
If the Remote desktop app remembers an old backend, replace it in remote connection settings. If an agent project still points at an old backend, rerun `sovara connect-agent` from the new project settings.
|