3 Agent Configuration and Reviewed Capabilities
Part I · The system in action
Configuration implementation: reference snapshot 45a903c · Parser ceiling: 65,536 bytes
Configuration should make the agent smaller and more predictable. The checked-in agent.yaml selects reviewed identifiers and bounded settings; it cannot load code, introduce a destination, provide credentials, or turn generated text into authority.
3.1 One configuration, one interpretation
agent.yaml is the sole implicit live-agent configuration. The server reads one bounded local file before it starts serving requests. It does not merge several files, interpolate environment variables, fetch includes, or accept request-time changes.
The root shape is intentionally small:
version: 1
server:
host: 127.0.0.1
port: 8787
coordinator:
model: openai/gpt-5.4
maxOutputTokens: 128000
inputFiles:
maxFiles: 4
maxDecodedBytesPerFile: 5242880
maxDecodedBytesPerRequest: 10485760
extractionTimeoutMs: 60000
skills:
- name: business-tech-presentation
tools:
- name: image_understanding
provider: openai
model: gpt-5.4
maxCalls: 10
- name: web_search
model: gpt-5.4
maxCalls: 300
- name: read_source
access: public-https
maxCalls: 100
- name: code_interpreter
maxCalls: 10
- name: presentation_builder
maxCalls: 2The complete checked-in file supplies every reviewed limit. The excerpt shows the principle: names select statically compiled components; fields narrow their operation.
3.2 A reviewed static catalog
A tool name is accepted only when the parser has an explicit branch for that exact identifier:
image_understanding
web_search
read_source
code_interpreter
presentation_builder
The reviewed skill catalog currently contains:
business-tech-presentation
This is not dynamic discovery. A configuration entry cannot point to a directory, npm package, URL, script, module, prompt file, class name, or executable. Adding a new identifier requires a source change, review, tests, and a new immutable revision.
The same rule applies to settings. Each tool branch accepts only fields meaningful to that implementation. For example, read_source can select public-https, call count, timeout, and response ceiling. It cannot accept arbitrary headers, a proxy, credentials, a private-network exception, or a custom fetch module.
3.3 Strict YAML admission
The loader limits the file to 65,536 bytes and parses it with unique-key enforcement. Startup rejects:
- duplicate mapping keys;
- YAML aliases;
- unsupported tags or parser warnings;
- unknown root, server, coordinator, input, skill, or tool fields;
- unknown skill and tool names;
- duplicate skill or tool selections;
- a missing explicit
toolsarray; - too many selected entries;
- values of the wrong YAML type; and
- out-of-range limits.
Failing on unknown fields is important. Ignoring maxCall when the reviewed field is maxCalls would silently remove the operator’s intended bound. Treating the typo as startup failure keeps the effective policy observable.
The loader converts YAML to a plain value only after rejecting aliases. There is no anchor-based reuse, merge-key expansion, or tag-directed construction. This is a defense against ambiguous configuration, not a claim that YAML parsing alone secures the application.
3.4 Limits are server ceilings
inputFiles and per-tool settings are trusted deployment policy. A request or model-generated argument cannot raise them.
| Limit family | Examples | Enforcement owner |
|---|---|---|
| Listener | loopback host, port | startup and server construction |
| Coordinator | selected provider/model route, maximum output tokens | route admission and model adapter |
| Input | file count, encoded/decoded bytes, extracted characters, retained bytes | ordered-input and asset registry |
| Extraction | timeout and process-wide concurrency | ingestion worker controller |
| Image | bytes, dimensions, pixels, frame count | image admission and decoder |
| Tool | calls, sources, timeout, code/output size | request-scoped tool runtime |
| Presentation | calls, slides, text, artifact bytes, TTL | builder and artifact store |
Bounds compose; they do not replace one another. Passing the HTTP body limit does not imply that every contained file passes decoded-byte or extraction limits. A configured timeout does not authorize a tool call, and a call count does not prove the selected provider can satisfy the request.
3.5 Skills and tools are separate selections
A skill is reviewed non-executable procedure. A tool is a separately authorized executable capability. Their configuration arrays remain distinct:
skill → reviewed instructions and declared resources
tool → compiled executor with schema, policy, limits, and effects
The current presentation procedure requires the bounded presentation builder. Startup therefore rejects either half selected alone. This dependency check prevents two misleading states:
- guidance that promises an unavailable builder; and
- a builder selected without the reviewed procedure expected by this application profile.
The dependency is static and application-specific. Loading the skill later does not register the tool, spend its budget, choose a provider, or widen any limit. Chapter 9 owns progressive disclosure and the full presentation case study.
3.6 What cannot appear in agent.yaml
The configuration intentionally excludes:
- API keys, bearer tokens, cookies, or credential-file references;
- arbitrary endpoint or redirect destinations;
- request headers;
- host filesystem paths;
- modules, plugins, packages, commands, or executable code;
- arbitrary prompts or model-generated policies;
- remote assets or presentation templates;
- dynamically discovered tools; and
- tenant, principal, or approval assertions.
Provider credentials and reviewed endpoint overrides, when needed, enter the trusted server process through the deployment environment. Keeping them out of YAML prevents an otherwise shareable capability selector from becoming a secret bundle. Environment ownership is not intrinsically safe; production deployment still needs a credential and configuration control plane.
3.7 Selecting a coordinator
The coordinator value has a bounded provider/model form with a reviewed provider prefix. This selects a route supported by server code; it does not accept a URL. The server rejects an unconfigured prefix rather than guessing or silently falling back.
A selected route is still only a declaration. Account access, regional availability, context limits, input types, and task quality require separate evidence. Chapter 14 owns feature admission and fallback. Chapter 5 owns provider construction and translation.
3.8 Explicit local customization
An operator can copy the reviewed file and point the server to one alternative path:
cp agent.yaml agent.local.yaml
PORTABLE_AGENTS_CONFIG=agent.local.yaml bun run serve:liveThere is no merge with the checked-in file. The selected file must satisfy the complete schema. An omitted tools key fails rather than restoring defaults.
The former implicit server.yaml name is rejected with a migration error. It can be loaded only through an explicit PORTABLE_AGENTS_CONFIG path. This prevents stale legacy configuration from being silently interpreted as the current policy.
Legacy WEB_SEARCH_* environment overrides are also rejected. Search enablement and limits belong to the YAML tool selection; provider credentials and approved endpoint settings remain in the server environment. Mixing both mechanisms would make the effective configuration difficult to review.
3.10 Startup is the failure boundary
Malformed or contradictory configuration fails before the listener accepts work. Startup errors identify the field category without echoing secrets or the full file. The process does not continue with a partial tool list, guessed defaults, or a disabled validation branch.
Useful startup diagnostics include the effective loopback address, coordinator routes, and selected reviewed tools/skills. They should not include API keys, endpoint credentials, prompt bodies, or complete configuration text.
This design favors availability loss over policy ambiguity. A production supervisor may restart a corrected deployment; it should not reinterpret invalid policy while requests are active.
3.11 Deterministic evidence
The reference tests cover:
- defaults and the complete checked-in file;
- unknown and duplicate tools;
- unknown and duplicate skills;
- extra fields at every relevant level;
- malformed numbers and limit ranges;
- aliases, tags, and duplicate YAML keys;
- missing explicit tool selection;
- presentation skill/builder dependency mismatch;
- loopback-only binding;
- legacy filename and environment rejection; and
- startup wiring from parsed settings to the selected compiled tools.
These tests establish parser and construction behavior for the named revision. They do not establish production principal authentication, secret management, deployment approval, or live provider capability.
3.12 Failure modes
3.12.1 Configuration as plugin loader
A path or package field turns declarative selection into code execution. Reviewed IDs avoid that hidden authority expansion.
3.12.2 Permissive unknown fields
Ignoring a typo can remove a limit while startup appears healthy. Strict field sets make drift fail visibly.
3.12.3 Tool selection as blanket permission
A selected tool still needs request-scoped authorization and execution admission. Startup cannot know the future principal, arguments, effect history, or cancellation state.
3.12.4 Skill text as capability grant
Instructions can shape model behavior but cannot register an executor or widen policy. Treating text as authority recreates prompt injection at the configuration boundary.
3.12.5 Capability declaration as evidence
A model route listed in configuration may be unavailable or semantically unsuitable. Replacement evidence belongs to Chapter 14, not the YAML parser.
3.13 Pattern summary
Use one bounded, strict, declarative selector over a static reviewed catalog. Reject ambiguity at startup. Keep credentials, destinations, code loading, principal identity, capability evidence, and invocation authorization in their own trusted boundaries.
3.14 Exercises
- Add a hypothetical
email_sendertool. List the source changes required without adding a module or path field to YAML. - Explain why
tools: []is safer than an omitted tools key that means “use defaults.” - Construct a duplicate-key YAML example whose permissive interpretation would widen a limit.
- Identify which of selection, capability evidence, invocation authorization, and execution admission should reject an exhausted call budget.
- Design a migration from one configuration version to another without silently accepting old fields.
3.15 Chapter contract
- Scope:
agent.yaml, static reviewed skill/tool selection, strict syntax and fields, bounded settings, dependency checks, startup failure, and the distinction between selection and authority. - Canonical claims: configuration selects reviewed compiled components and ceilings; it cannot load code or authorize a future invocation.
- Migration inputs: former capability/configuration material and the current strict live-server parser.
- Evidence gates: deterministic parser, wiring, dependency, and startup-failure tests for an immutable snapshot.
- Demonstration slots: the hero shows the effective selected tool/skill profile; configuration enforcement is established by tests rather than model behavior.
- Source-claim ledger: current skill identity and dependencies are tied to snapshot
45a903c; olderv0.4.0parser evidence remains historical where applicable. - Exclusions: provider translation belongs to Chapter 5, skill procedure to Chapter 9, capability substitution to Chapter 14, and principal authorization to Chapters 8 and 17.