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.
Files changed (85) hide show
  1. {sovara-0.3.3 → sovara-0.3.4}/PKG-INFO +5 -1
  2. {sovara-0.3.3 → sovara-0.3.4}/README.md +2 -0
  3. {sovara-0.3.3 → sovara-0.3.4}/pyproject.toml +6 -2
  4. sovara-0.3.4/src/sovara/assets/sovara/SKILL.md +68 -0
  5. sovara-0.3.4/src/sovara/assets/sovara/enterprise-azure.md +496 -0
  6. sovara-0.3.4/src/sovara/assets/sovara/enterprise-palantir.md +82 -0
  7. sovara-0.3.4/src/sovara/assets/sovara/evals/evals.json +55 -0
  8. sovara-0.3.4/src/sovara/assets/sovara/evals/trigger_queries.json +126 -0
  9. sovara-0.3.4/src/sovara/assets/sovara/install-desktop-app.md +82 -0
  10. sovara-0.3.4/src/sovara/assets/sovara/install-python-sdk.md +83 -0
  11. sovara-0.3.4/src/sovara/assets/sovara/install-ts-sdk.md +103 -0
  12. sovara-0.3.4/src/sovara/assets/sovara/optimizing-agents.md +217 -0
  13. sovara-0.3.4/src/sovara/assets/sovara/references/cli-reference.md +191 -0
  14. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/so_tool.py +114 -189
  15. sovara-0.3.4/src/sovara/common/agent_credentials.py +90 -0
  16. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/config.py +113 -12
  17. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/constants.py +28 -42
  18. sovara-0.3.4/src/sovara/common/db_credentials.py +85 -0
  19. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/node_naming.py +13 -2
  20. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/utils.py +33 -2
  21. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/agent_runner.py +46 -87
  22. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parser.py +2 -2
  23. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/claude_sdk_patch.py +10 -62
  24. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/priors.py +0 -3
  25. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/public.py +32 -52
  26. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/record_entrypoint.py +0 -4
  27. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/runtime_client.py +2 -45
  28. {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/PKG-INFO +5 -1
  29. {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/SOURCES.txt +12 -2
  30. {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/requires.txt +1 -0
  31. sovara-0.3.3/src/sovara/assets/SKILL.md +0 -908
  32. sovara-0.3.3/src/sovara/common/user.py +0 -89
  33. {sovara-0.3.3 → sovara-0.3.4}/setup.cfg +0 -0
  34. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/__init__.py +0 -0
  35. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/assets/__init__.py +0 -0
  36. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/__init__.py +0 -0
  37. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/cli/sovara.py +0 -0
  38. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/__init__.py +0 -0
  39. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/annotations.py +0 -0
  40. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/code_version.py +0 -0
  41. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/code_version_remote_cases.json +0 -0
  42. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/custom_metrics.py +0 -0
  43. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/edit_io_exclude_patterns.json +0 -0
  44. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/endpoint_patterns.json +0 -0
  45. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/lifecycle.py +0 -0
  46. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/log_redaction.py +0 -0
  47. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/logger.py +0 -0
  48. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/payload_display.py +0 -0
  49. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/priors_block.py +0 -0
  50. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/priors_block_guidance.json +0 -0
  51. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/project.py +0 -0
  52. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/run_logs.py +0 -0
  53. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/sse_utils.py +0 -0
  54. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/common/to_show_filters.py +0 -0
  55. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/__init__.py +0 -0
  56. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/context_manager.py +0 -0
  57. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/__init__.py +0 -0
  58. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/__init__.py +0 -0
  59. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/aiohttp_api_parser.py +0 -0
  60. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/claude_code_messages_api_parser.py +0 -0
  61. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/httpx_api_parser.py +0 -0
  62. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/mcp_api_parser.py +0 -0
  63. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/requests_api_parser.py +0 -0
  64. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/sse_utils.py +0 -0
  65. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/api_parsers/urllib3_api_parser.py +0 -0
  66. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/apply_monkey_patches.py +0 -0
  67. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/async_streaming.py +0 -0
  68. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/endpoint_whitelist.py +0 -0
  69. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/__init__.py +0 -0
  70. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/adk_patch.py +0 -0
  71. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/aiohttp_patch.py +0 -0
  72. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/httpx_patch.py +0 -0
  73. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/langchain_patch.py +0 -0
  74. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/mcp_patches.py +0 -0
  75. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/openai_agents_patch.py +0 -0
  76. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/requests_patch.py +0 -0
  77. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patches/urllib3_patch.py +0 -0
  78. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/patching_utils.py +0 -0
  79. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/to_show_filters.py +0 -0
  80. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/monkey_patching/tool_trace_utils.py +0 -0
  81. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/request_mutation.py +0 -0
  82. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/run_log_capture.py +0 -0
  83. {sovara-0.3.3 → sovara-0.3.4}/src/sovara/runner/trace.py +0 -0
  84. {sovara-0.3.3 → sovara-0.3.4}/src/sovara.egg-info/dependency_links.txt +0 -0
  85. {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
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
@@ -27,3 +27,5 @@ with sovara.run("support-agent"):
27
27
  The terminal command is distributed separately as the native Sovara CLI. Install
28
28
  that CLI for commands such as `sovara record`, `sovara status`, and
29
29
  `sovara probe`.
30
+
31
+ 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" = ["SKILL.md"]
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.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.