Skip to main content
Managed configuration lets a team or organisation supply shared defaults and enforceable policy from a remote URL or an on-disk managed directory — without changing how a single user’s config works.
This page is about CLI configuration distribution. It is unrelated to ManagedAgent runtime pages, which document Anthropic-hosted agents.
# Point the CLI at a team config and run as usual
export PRAISONAI_MANAGED_CONFIG_URL=https://example.com/team.yml
praisonai run "Summarise today's incidents"
Fully opt-in. With no managed source configured, resolution behaves byte-for-byte identical to before — no managed layer is added.

Quick Start

1

Point at a remote URL

export PRAISONAI_MANAGED_CONFIG_URL=https://example.com/team.yml
The file is fetched with a short timeout and cached on disk. Offline runs use the last-good cache.
2

Or point at a managed directory

For MDM / enterprise config management, drop a config.yaml (or .yml / .json) into a directory:
export PRAISONAI_MANAGED_CONFIG_DIR=/etc/praisonai
A managed config file looks like any other PraisonAI config, with optional policy keys:
# team.yml
agent:
  temperature: 0.3        # a suggested default (below local)
model_allowlist:          # enforced policy (above local)
  - gpt-4o
  - gpt-4o-mini
enforce: true             # default; set false to make the whole source advisory

Precedence Ladder

The managed layer splits into two: enforced policy sits above your local config, while managed defaults sit below it — so teams can suggest without clobbering deliberate local choices.
Order (highest wins)Layer
7Managed policy (permissions, model_allowlist) — enforced above local
6CLI args
5Environment variables
4Project config (walk-up)
3Global user config
2Managed non-policy defaults — below local so teams suggest, not clobber
1Built-in defaults

Enforcement vs. Advisory

Only two keys are treated as policy: permissions and model_allowlist. When enforced they replace (not merge or concat) their local counterpart wholesale — a local override of an enforced key is ignored, including nested local sub-keys the policy does not mention. Set enforce: false to make the entire managed source advisory.
Enforcement is a wholesale replace, not a merge. A managed permissions.bash.auto: false completely replaces any local permissions — none of the local sub-keys survive. This is easy to get wrong when reasoning about deep merges.

Agent-Perspective Example

Org policy shapes what any Agent(...) run can do — no code change needed on the developer’s side.
from praisonaiagents import Agent

# Org policy at /etc/praisonai/config.yaml says:
#   model_allowlist: [gpt-4o]
#   permissions.bash.auto: false

agent = Agent(name="Analyst", instructions="Analyse the sales data.")
agent.start("Summarise Q3 revenue")
# ✓ uses gpt-4o (the only allowed model)
# ✓ bash tools require confirmation (org policy overrides any local `auto: true`)

Configuration Keys

Set these under a managed: section in your global config, or via environment variables (env overrides the global section):
KeyTypeDefaultDescription
managed.urlstrNoneRemote URL to fetch (https, or loopback http)
managed.dirstrNoneManaged/enterprise directory (config.yaml/.yml/.json)
managed.timeoutfloat3.0Fetch timeout in seconds
managed.enforceboolTruefalse makes the whole source advisory
model_allowlistlist[str]NoneAllowed models (enforceable policy key)
permissionsdict{}Permission policy shape (enforceable policy key)
Environment variables (override the global managed: section):
VariableMaps to
PRAISONAI_MANAGED_CONFIG_URLmanaged.url
PRAISONAI_MANAGED_CONFIG_DIRmanaged.dir
PRAISONAI_MANAGED_CONFIG_TIMEOUTmanaged.timeout

Provenance

ConfigResolver.resolve_with_provenance() reports, per key, which layer set it. Enforced keys are marked enforced: True.
from praisonai_code.cli.configuration.resolver import ConfigResolver

resolver = ConfigResolver()
provenance = resolver.resolve_with_provenance()

print(provenance["model_allowlist"])
# {'value': ['gpt-4o', 'gpt-4o-mini'],
#  'layer': 'managed-policy:https://example.com/team.yml',
#  'source': 'https://example.com/team.yml',
#  'enforced': True}

print(provenance["agent.temperature"])
# {'value': 0.3, 'layer': 'managed:https://example.com/team.yml',
#  'source': 'https://example.com/team.yml'}
Layers are labelled managed: for defaults and managed-policy: for enforced keys.

Failure Modes

Fail-soft by design. The managed URL is fetched with a short timeout. On any failure the resolver uses the last-good cached copy under ~/.praison/state/, or — if there is none — simply skips the managed layer. A run is never blocked on the network.
No network? The cached copy at ~/.praison/state/managed-config-<hash>.json is used. With no cache, resolution proceeds as local-only.
Only https (or explicit loopback http) URLs resolving to a public host are fetched. Private, loopback, link-local, and cloud-metadata hosts (e.g. 169.254.169.254) are refused. file:// and other non-http(s) schemes are refused. A rejected URL fails soft to the cache and is never fetched.
If both dir and url are set, the managed directory loads first and the remote URL layers on top of it.

Best Practices

Put team preferences (agent.model, agent.provider) in the managed source as defaults so projects can still override them. Reserve permissions and model_allowlist for what the org must guarantee.
A directory drop (/etc/praisonai/config.yaml) needs no network and is the simplest path for config-management tools to push.
The SSRF guard only fetches https:// URLs resolving to public IPs. Host the managed config on a public HTTPS endpoint so it is never silently refused.
After a rollout, run resolve_with_provenance() and confirm the policy keys show layer: managed-policy:... and enforced: True.

Hierarchical Config

Project-aware config walk-up and deep merge

Permissions

The permission policy shape enforced by managed config

Config CLI

Inspect and edit resolved config

Policy CLI

Team policy controls