ecp.config.yaml). That split is deliberate: you can share Contexts without implicitly granting every recipient the same models, MCP servers, or credential sources.
Default-deny tool access
Orchestrators and executors cannot call tools unless explicitly allowed. Policies use an allowlist:Scoped permissions
- Tool access — Per-executor allowlists (e.g. read-only tools for analysts, write tools only for the publisher).
- Write controls — Modes:
forbid,propose-only,execute-if-allowed. OptionalrequireApprovalForfor specific tools. - Budgets —
maxToolCalls,maxRuntimeSecondsto cap cost and time per executor.
Execution trace
Every run should produce a reproducible trace, including:- Resolved Context snapshot
- Tool invocation log
- Agent outputs
- Execution timeline
- Policy decisions
ecp trace (and ecp trace list), optionally rendering the ASCII view with --output graph.
This supports compliance, debugging, and replay. Contexts are versioned and signed (roadmap) to avoid overly permissive configs being distributed by mistake.
Host system configuration and the security mirror (v0.5+)
The system config file (ecp.config.yaml, or path via --config) has two roles:
- Configure — Wiring and defaults:
models.providers,tools.servers,loggers.config,agents.endpoints,secrets, optionalexecutors.instances,memory.stores, andplugins.installs(where packaged plugins are recorded). Provider-specific options (for example OllamabaseURL) live under each entry’sconfigobject. security— The same area names, but only allow-lists and defaults: what may run at all, regardless of what a Context declares.
security include:
security.models—allowProviders,defaultProviders(keys must exist undermodels.providers).security.tools—allowServers(logical MCP server names undertools.servers).security.plugins— Global extension policy (PluginSecurityPolicy): which plugin kinds may load (allowKinds, includingtoolfor MCP-governed servers), sources (allowSourceTypessuch asbuiltin), and ids (allowIds/denyIds). This is separate fromplugins.installs, which is provenance and install paths—not the allow-list.security.loggers,security.secrets,security.executors,security.memory,security.agents— Same pattern when those areas are used.
version: "0.5" (schema version of the system config document). Runtimes may reject other values.
Why this design helps in production
- Non-bypassable host gates — Even if a Context lists a model provider, an MCP server, or a plugin kind, the host can refuse to wire it unless it appears under the corresponding
security.*allow-list. That is enforcement in config and loaders, not in a system prompt the agent might drift around. - Clear separation of concerns — Contexts stay portable descriptions of orchestration and per-executor policies; the host file answers “on this machine, which integrations exist and which are permitted.” Operations teams can tighten
securitywithout forking every Context. - Composable policy — Context
policies.toolAccessstill does per-executor default-deny and fine-grained tool allowlists;security.tools.allowServerscaps which server names may even connect. A malicious or over-broad manifest cannot summon a server that was never installed or allowed on the host. - Extension surface control —
security.pluginsrestricts which kinds of plugins (provider, executor, logger, memory, tool, …) and which ids may participate. OmittingtoolfromallowKinds, for example, is how implementations can refuse MCP connections governed as tool plugins when you want a read-only or model-only deployment. - Auditability — Allow-lists and defaults are plain data next to wiring. Together with traces, reviewers can answer what was configured to be possible versus what a given run attempted.
ecp config security get, ecp config security plugins update, plus ecp config plugins, ecp config models, ecp config tools, and ecp config secrets (ecp config --help for the full tree).
Full config specification (authoritative references)
- SPEC.md — Host system configuration (
ecp.config.yaml) — Normative description of the two roles,version,securitymirror, MCP/toolkind, and A2A endpoint shape. - config/ecp.config.example.yaml — Annotated example aligned with the enforced shape (also validated in repo tests).
- TypeScript:
ECPSystemConfigandSecurityConfiginpackages/runtime— Programmatic reference for implementers.
Context plugins block
The Context manifest’s plugins section declares which model providers, executors, and auxiliary plugins (loggers, memory, …) the Context expects, with versions pinned per PluginReference and an optional plugins.security object for manifest-scoped plugin policy. The host still applies security.* in ecp.config.yaml; the Context cannot override a denied provider or server.
Secrets and tool credentials
ECP resolves MCP and HTTP credentials using explicit provider namespaces in system config, under each server’s optional credentials block:tools.servers.<name>.credentials.bindings[].source:
| Provider id | Role |
|---|---|
process.env | Values from the real process environment (shell, CI, container env). |
dot.env | Values from a .env-style file on disk. The default path comes from system config (secrets.providers.dot.env.path); ecp run, ecp validate, ecp trace, and related commands accept --environment <path> to override that file for one invocation. |
os.secrets | Values from the OS credential manager; each secret uses an ecp://<key> keyring target (default ref id — the provider id is not in the URI). Use ecp config secrets to store or rotate them. |
dot.env does not inject its variables into process.env; a binding must use source.provider: process.env to read the shell, and source.provider: dot.env to read the file. That keeps “what the agent sees in MCP env” explicit and avoids accidental leakage from a local .env into the global process.
Config vs runtime: ecp config secrets manages persisted keys and reads dot.env only from ecp.config.* — it does not take --environment. Runtime-oriented commands are where the per-run file override applies.
For CLI details and examples, see the CLI reference and the packages/cli README. For secret defaults and policy flags in YAML, see ecp config secrets yaml (get, set-default-provider, set-policy).
Principles in short
- Least-privilege execution per executor and at the host via the
securitymirror - Short-lived credentials and full audit logging (runtime responsibility)
- Explicit secret namespaces so
.envfiles are never silently merged intoprocess.env - Provenance tracking of context sources
- Contexts should make overly-permissive configurations difficult to express and distribute