#81 - .env vars applied to settings

deci committed Dec 9, 2025 at 16:47 UTC 2400dd5882007d250740286ac1e5d5257207df25
4 files changed +164 -71
README.md
+1
@@ -81,6 +81,7 @@ Agent Zero now supports **Projects** – isolated workspaces with their own prom
81 - The framework does not guide or limit the agent in any way. There are no hard-coded rails that agents have to follow.
82 - Every prompt, every small message template sent to the agent in its communication loop can be found in the **prompts/** folder and changed.
83 - Every default tool can be found in the **python/tools/** folder and changed or copied to create new predefined tools.
84 +- **Automated configuration** via `A0_SET_` environment variables for deployment automation and easy setup.
85
86 ![Prompts](/docs/res/prompts.png)
87
docs/development.md
+14
@@ -149,6 +149,20 @@ You're now ready to contribute to Agent Zero, create custom extensions, or modif
149 - See [extensibility](extensibility.md) for instructions on how to create custom extensions.
150 - See [contribution](contribution.md) for instructions on how to contribute to the framework.
151
152 +## Configuration via Environment Variables
153 +
154 +For development and testing, you can override default settings using the `.env` file with `A0_SET_` prefixed variables:
155 +
156 +```env
157 +# Add to your .env file
158 +A0_SET_chat_model_provider=ollama
159 +A0_SET_chat_model_name=llama3.2
160 +A0_SET_chat_model_api_base=http://localhost:11434
161 +A0_SET_memory_recall_interval=5
162 +```
163 +
164 +These environment variables automatically override the hardcoded defaults in `get_default_settings()` without modifying code. Useful for testing different configurations or multi-environment setups.
165 +
166 ## Want to build your docker image?
167 - You can use the `DockerfileLocal` to build your docker image.
168 - Navigate to your project root in the terminal and run `docker build -f DockerfileLocal -t agent-zero-local --build-arg CACHE_DATE=$(date +%Y-%m-%d:%H:%M:%S) .`
docs/installation.md
+47 -1
@@ -93,9 +93,55 @@ The following user guide provides instructions for installing and running Agent
93 - `/tmp/settings.json` - Your Agent Zero settings
94
95 > [!TIP]
96 -> Choose a location that's easy to access and backup. All your Agent Zero data
96 +> Choose a location that's easy to access and backup. All your Agent Zero data
97 > will be directly accessible in this directory.
98
99 +### Automated Configuration via Environment Variables
100 +
101 +Agent Zero settings can be automatically configured using environment variables with the `A0_SET_` prefix in your `.env` file. This enables automated deployments without manual configuration.
102 +
103 +**Usage:**
104 +Add variables to your `.env` file in the format:
105 +```
106 +A0_SET_{setting_name}={value}
107 +```
108 +
109 +**Examples:**
110 +```env
111 +# Model configuration
112 +A0_SET_chat_model_provider=anthropic
113 +A0_SET_chat_model_name=claude-3-5-sonnet-20241022
114 +A0_SET_chat_model_ctx_length=200000
115 +
116 +# Memory settings
117 +A0_SET_memory_recall_enabled=true
118 +A0_SET_memory_recall_interval=5
119 +
120 +# Agent configuration
121 +A0_SET_agent_profile=custom
122 +A0_SET_agent_memory_subdir=production
123 +```
124 +
125 +**Docker usage:**
126 +When running Docker, you can pass these as environment variables:
127 +```bash
128 +docker run -p 50080:80 \
129 + -e A0_SET_chat_model_provider=anthropic \
130 + -e A0_SET_chat_model_name=claude-3-5-sonnet-20241022 \
131 + agent0ai/agent-zero
132 +```
133 +
134 +**Type conversion:**
135 +- Strings are used as-is
136 +- Numbers are automatically converted (e.g., "100000" becomes integer 100000)
137 +- Booleans accept: true/false, 1/0, yes/no, on/off (case-insensitive)
138 +- Dictionaries must be valid JSON (e.g., `{"temperature": "0"}`)
139 +
140 +**Notes:**
141 +- These override default values in settings.json
142 +- Sensitive settings (API keys, passwords) use their existing environment variables
143 +- Container/process restart required for changes to take effect
144 +
145 2.3. Run the container:
146 - In Docker Desktop, go back to the "Images" tab
147 - Click the `Run` button next to the `agent0ai/agent-zero` image
python/helpers/settings.py
+102 -70
@@ -4,7 +4,7 @@ import json
4 import os
5 import re
6 import subprocess
7 -from typing import Any, Literal, TypedDict, cast
7 +from typing import Any, Literal, TypedDict, cast, TypeVar
8
9 import models
10 from python.helpers import runtime, whisper, defer, git
@@ -15,6 +15,38 @@ from python.helpers.secrets import get_default_secrets_manager
15 from python.helpers import dirty_json
16
17
18 +T = TypeVar('T')
19 +
20 +def get_default_value(name: str, value: T) -> T:
21 + """
22 + Load setting value from .env with A0_SET_ prefix, falling back to default.
23 +
24 + Args:
25 + name: Setting name (will be prefixed with A0_SET_)
26 + value: Default value to use if env var not set
27 +
28 + Returns:
29 + Environment variable value (type-normalized) or default value
30 + """
31 + env_value = dotenv.get_dotenv_value(f"A0_SET_{name}")
32 +
33 + if env_value is None:
34 + return value
35 +
36 + # Normalize type to match value param type
37 + try:
38 + if isinstance(value, bool):
39 + return env_value.lower() in ('true', '1', 'yes', 'on') # type: ignore
40 + elif isinstance(value, dict):
41 + return json.loads(env_value) # type: ignore
42 + elif isinstance(value, str):
43 + return str(env_value).strip() # type: ignore
44 + else:
45 + return type(value)(env_value) # type: ignore
46 + except (ValueError, TypeError, json.JSONDecodeError):
47 + return value
48 +
49 +
50 class Settings(TypedDict):
51 version: str
52
@@ -1456,83 +1488,83 @@ def _write_sensitive_settings(settings: Settings):
1488 def get_default_settings() -> Settings:
1489 return Settings(
1490 version=_get_version(),
1459 - chat_model_provider="openrouter",
1460 - chat_model_name="openai/gpt-4.1",
1461 - chat_model_api_base="",
1462 - chat_model_kwargs={"temperature": "0"},
1463 - chat_model_ctx_length=100000,
1464 - chat_model_ctx_history=0.7,
1465 - chat_model_vision=True,
1466 - chat_model_rl_requests=0,
1467 - chat_model_rl_input=0,
1468 - chat_model_rl_output=0,
1469 - util_model_provider="openrouter",
1470 - util_model_name="openai/gpt-4.1-mini",
1471 - util_model_api_base="",
1472 - util_model_ctx_length=100000,
1473 - util_model_ctx_input=0.7,
1474 - util_model_kwargs={"temperature": "0"},
1475 - util_model_rl_requests=0,
1476 - util_model_rl_input=0,
1477 - util_model_rl_output=0,
1478 - embed_model_provider="huggingface",
1479 - embed_model_name="sentence-transformers/all-MiniLM-L6-v2",
1480 - embed_model_api_base="",
1481 - embed_model_kwargs={},
1482 - embed_model_rl_requests=0,
1483 - embed_model_rl_input=0,
1484 - browser_model_provider="openrouter",
1485 - browser_model_name="openai/gpt-4.1",
1486 - browser_model_api_base="",
1487 - browser_model_vision=True,
1488 - browser_model_rl_requests=0,
1489 - browser_model_rl_input=0,
1490 - browser_model_rl_output=0,
1491 - browser_model_kwargs={"temperature": "0"},
1492 - browser_http_headers={},
1493 - memory_recall_enabled=True,
1494 - memory_recall_delayed=False,
1495 - memory_recall_interval=3,
1496 - memory_recall_history_len=10000,
1497 - memory_recall_memories_max_search=12,
1498 - memory_recall_solutions_max_search=8,
1499 - memory_recall_memories_max_result=5,
1500 - memory_recall_solutions_max_result=3,
1501 - memory_recall_similarity_threshold=0.7,
1502 - memory_recall_query_prep=True,
1503 - memory_recall_post_filter=True,
1504 - memory_memorize_enabled=True,
1505 - memory_memorize_consolidation=True,
1506 - memory_memorize_replace_threshold=0.9,
1491 + chat_model_provider=get_default_value("chat_model_provider", "openrouter"),
1492 + chat_model_name=get_default_value("chat_model_name", "openai/gpt-4.1"),
1493 + chat_model_api_base=get_default_value("chat_model_api_base", ""),
1494 + chat_model_kwargs=get_default_value("chat_model_kwargs", {"temperature": "0"}),
1495 + chat_model_ctx_length=get_default_value("chat_model_ctx_length", 100000),
1496 + chat_model_ctx_history=get_default_value("chat_model_ctx_history", 0.7),
1497 + chat_model_vision=get_default_value("chat_model_vision", True),
1498 + chat_model_rl_requests=get_default_value("chat_model_rl_requests", 0),
1499 + chat_model_rl_input=get_default_value("chat_model_rl_input", 0),
1500 + chat_model_rl_output=get_default_value("chat_model_rl_output", 0),
1501 + util_model_provider=get_default_value("util_model_provider", "openrouter"),
1502 + util_model_name=get_default_value("util_model_name", "openai/gpt-4.1-mini"),
1503 + util_model_api_base=get_default_value("util_model_api_base", ""),
1504 + util_model_ctx_length=get_default_value("util_model_ctx_length", 100000),
1505 + util_model_ctx_input=get_default_value("util_model_ctx_input", 0.7),
1506 + util_model_kwargs=get_default_value("util_model_kwargs", {"temperature": "0"}),
1507 + util_model_rl_requests=get_default_value("util_model_rl_requests", 0),
1508 + util_model_rl_input=get_default_value("util_model_rl_input", 0),
1509 + util_model_rl_output=get_default_value("util_model_rl_output", 0),
1510 + embed_model_provider=get_default_value("embed_model_provider", "huggingface"),
1511 + embed_model_name=get_default_value("embed_model_name", "sentence-transformers/all-MiniLM-L6-v2"),
1512 + embed_model_api_base=get_default_value("embed_model_api_base", ""),
1513 + embed_model_kwargs=get_default_value("embed_model_kwargs", {}),
1514 + embed_model_rl_requests=get_default_value("embed_model_rl_requests", 0),
1515 + embed_model_rl_input=get_default_value("embed_model_rl_input", 0),
1516 + browser_model_provider=get_default_value("browser_model_provider", "openrouter"),
1517 + browser_model_name=get_default_value("browser_model_name", "openai/gpt-4.1"),
1518 + browser_model_api_base=get_default_value("browser_model_api_base", ""),
1519 + browser_model_vision=get_default_value("browser_model_vision", True),
1520 + browser_model_rl_requests=get_default_value("browser_model_rl_requests", 0),
1521 + browser_model_rl_input=get_default_value("browser_model_rl_input", 0),
1522 + browser_model_rl_output=get_default_value("browser_model_rl_output", 0),
1523 + browser_model_kwargs=get_default_value("browser_model_kwargs", {"temperature": "0"}),
1524 + browser_http_headers=get_default_value("browser_http_headers", {}),
1525 + memory_recall_enabled=get_default_value("memory_recall_enabled", True),
1526 + memory_recall_delayed=get_default_value("memory_recall_delayed", False),
1527 + memory_recall_interval=get_default_value("memory_recall_interval", 3),
1528 + memory_recall_history_len=get_default_value("memory_recall_history_len", 10000),
1529 + memory_recall_memories_max_search=get_default_value("memory_recall_memories_max_search", 12),
1530 + memory_recall_solutions_max_search=get_default_value("memory_recall_solutions_max_search", 8),
1531 + memory_recall_memories_max_result=get_default_value("memory_recall_memories_max_result", 5),
1532 + memory_recall_solutions_max_result=get_default_value("memory_recall_solutions_max_result", 3),
1533 + memory_recall_similarity_threshold=get_default_value("memory_recall_similarity_threshold", 0.7),
1534 + memory_recall_query_prep=get_default_value("memory_recall_query_prep", True),
1535 + memory_recall_post_filter=get_default_value("memory_recall_post_filter", True),
1536 + memory_memorize_enabled=get_default_value("memory_memorize_enabled", True),
1537 + memory_memorize_consolidation=get_default_value("memory_memorize_consolidation", True),
1538 + memory_memorize_replace_threshold=get_default_value("memory_memorize_replace_threshold", 0.9),
1539 api_keys={},
1540 auth_login="",
1541 auth_password="",
1542 root_password="",
1511 - agent_profile="agent0",
1512 - agent_memory_subdir="default",
1513 - agent_knowledge_subdir="custom",
1514 - rfc_auto_docker=True,
1515 - rfc_url="localhost",
1543 + agent_profile=get_default_value("agent_profile", "agent0"),
1544 + agent_memory_subdir=get_default_value("agent_memory_subdir", "default"),
1545 + agent_knowledge_subdir=get_default_value("agent_knowledge_subdir", "custom"),
1546 + rfc_auto_docker=get_default_value("rfc_auto_docker", True),
1547 + rfc_url=get_default_value("rfc_url", "localhost"),
1548 rfc_password="",
1517 - rfc_port_http=55080,
1518 - rfc_port_ssh=55022,
1519 - shell_interface="local" if runtime.is_dockerized() else "ssh",
1520 - stt_model_size="base",
1521 - stt_language="en",
1522 - stt_silence_threshold=0.3,
1523 - stt_silence_duration=1000,
1524 - stt_waiting_timeout=2000,
1525 - tts_kokoro=True,
1526 - mcp_servers='{\n "mcpServers": {}\n}',
1527 - mcp_client_init_timeout=10,
1528 - mcp_client_tool_timeout=120,
1529 - mcp_server_enabled=False,
1549 + rfc_port_http=get_default_value("rfc_port_http", 55080),
1550 + rfc_port_ssh=get_default_value("rfc_port_ssh", 55022),
1551 + shell_interface=get_default_value("shell_interface", "local" if runtime.is_dockerized() else "ssh"),
1552 + stt_model_size=get_default_value("stt_model_size", "base"),
1553 + stt_language=get_default_value("stt_language", "en"),
1554 + stt_silence_threshold=get_default_value("stt_silence_threshold", 0.3),
1555 + stt_silence_duration=get_default_value("stt_silence_duration", 1000),
1556 + stt_waiting_timeout=get_default_value("stt_waiting_timeout", 2000),
1557 + tts_kokoro=get_default_value("tts_kokoro", True),
1558 + mcp_servers=get_default_value("mcp_servers", '{\n "mcpServers": {}\n}'),
1559 + mcp_client_init_timeout=get_default_value("mcp_client_init_timeout", 10),
1560 + mcp_client_tool_timeout=get_default_value("mcp_client_tool_timeout", 120),
1561 + mcp_server_enabled=get_default_value("mcp_server_enabled", False),
1562 mcp_server_token=create_auth_token(),
1531 - a2a_server_enabled=False,
1563 + a2a_server_enabled=get_default_value("a2a_server_enabled", False),
1564 variables="",
1565 secrets="",
1534 - litellm_global_kwargs={},
1535 - update_check_enabled=True,
1566 + litellm_global_kwargs=get_default_value("litellm_global_kwargs", {}),
1567 + update_check_enabled=get_default_value("update_check_enabled", True),
1568 )
1569
1570