Profiles
BeamWeaver has profiles, but the names and integration points are not a one-for-one copy of the Python Deep Agents page. There are three distinct profile concepts:
| Profile kind | BeamWeaver API | Controls | Automatic? |
|---|---|---|---|
| Capability profile |
BeamWeaver.Agent.CapabilityProfile and BeamWeaver.Agent.CapabilityProfileConfig
| Compatibility/profile data such as prompt suffixes, model-visible tool descriptions, excluded tools, excluded middleware, extra middleware, and general-purpose subagent metadata. |
Registry and merge logic exist; normal BeamWeaver.Agent.build(...) and use BeamWeaver.Agent builds do not automatically overlay these profiles.
|
| Provider profile |
BeamWeaver.Agent.ProviderProfile
| Model-construction defaults for provider/model strings. | Yes, for binary or atom model identifiers passed to agents. |
| Model profile |
BeamWeaver.Models.Profile and BeamWeaver.Models.ProfileRegistry
| Provider/model capabilities such as context window, tool calling, structured output, streaming, modalities, tokenizer, and supported params. |
Yes, through BeamWeaver.Models.init_chat_model/2 and provider structs.
|
Use provider profiles when you want model initialization defaults. Use model profiles when you need capability metadata. Use capability profiles when you are building your own compatibility layer and want serializable profile data that mirrors Python Deep Agents profile shapes.
Capability Profiles
BeamWeaver.Agent.CapabilityProfile stores provider/model-specific compatibility preferences inspired by Python Deep Agents profile data:
alias BeamWeaver.Agent.CapabilityProfile
:ok =
CapabilityProfile.register_capability_profile(
"anthropic:claude-sonnet-4-6",
CapabilityProfile.new(
system_prompt_suffix: "Use tools carefully and keep notes in files.",
excluded_tools: ["execute"],
tool_description_overrides: %{
"grep" => "Search UTF-8 files for exact text."
},
general_purpose_subagent: %{
enabled: false
}
)
)
profile = CapabilityProfile.get_capability_profile("anthropic:claude-sonnet-4-6")
Profile keys use the same provider or provider/model shape as the official docs:
-
Provider-level keys such as
"anthropic"apply to every model for that provider. -
Model-level keys such as
"anthropic:claude-sonnet-4-6"merge on top of the provider profile. -
There is no wildcard key for every provider.
BeamWeaver ships built-in capability profiles for Anthropic Claude 4.5/4.6/4.7 families and OpenAI Codex model names. Inspect the known keys at runtime:
BeamWeaver.Agent.CapabilityProfile.builtin_keys()
Fields
CapabilityProfile.new/1 accepts these Deep Agents-compatible names:
| Field | Meaning |
|---|---|
:base_system_prompt
| Replacement base prompt text for custom composed-agent assembly. |
:system_prompt_suffix or :prompt_suffix
| Text to append to a custom assembled prompt. |
:tool_description_overrides or :tool_descriptions
| Map of tool name to model-visible description. |
:excluded_tools
| Tool names a custom harness should hide from the model. |
:excluded_middleware
| Middleware modules or public names a custom harness should drop. |
:extra_middleware or :middleware
| Extra middleware instances, modules, or a zero-arity factory. |
:general_purpose_subagent
|
%GeneralPurposeSubagentProfile{} data or a map with :enabled, :description, and :system_prompt.
|
The struct also has :default_subagent? for compatibility with the general-purpose subagent profile. Normal BeamWeaver agent builds do not inject a default general-purpose subagent; pass explicit subagents when you want a task tool.
Merge Semantics
Provider and exact-model capability profiles merge with additive semantics:
| Field | Merge behavior |
|---|---|
base_system_prompt, prompt_suffix
| Override wins when set. |
tool_descriptions
| Maps merge by tool name; override wins on conflicts. |
excluded_tools, excluded_middleware
| Lists are unioned. |
middleware
| Merged by concrete middleware key; override replaces matching base middleware and appends new entries. |
general_purpose_subagent
| Merged field by field. |
Re-registering a key merges the new profile over the existing one rather than replacing it.
Config Files
Use BeamWeaver.Agent.CapabilityProfileConfig for the serializable subset. It round-trips maps that can be stored as JSON, YAML, or application config:
alias BeamWeaver.Agent.{CapabilityProfile, CapabilityProfileConfig}
config =
CapabilityProfileConfig.from_map(%{
"system_prompt_suffix" => "Respond briefly.",
"excluded_tools" => ["execute", "grep"],
"tool_description_overrides" => %{
"ls" => "List virtual files."
},
"general_purpose_subagent" => %{
"enabled" => false
}
})
profile = CapabilityProfileConfig.to_capability_profile(config)
:ok = CapabilityProfile.register_capability_profile("openai:gpt-5.4", profile)
CapabilityProfileConfig intentionally excludes runtime-only fields such as middleware instances and factories.
Applying Harness Behavior
The profile registry is available for custom harness code:
profile = CapabilityProfile.for_model(model, "anthropic:claude-sonnet-4-6")
middleware =
profile
|> CapabilityProfile.materialize_extra_middleware()
|> Kernel.++(app_middleware)
For normal BeamWeaver agents, configure composed capability behavior directly on the agent:
BeamWeaver.Agent.build(
model: "anthropic:claude-sonnet-4-6",
filesystem: BeamWeaver.Filesystem.State.new(),
exclude_tools: ["execute"],
tool_descriptions: %{"grep" => "Search project files."},
subagents: [
BeamWeaver.Agent.Subagent.Spec.new(
name: "researcher",
description: "Collect source-backed findings.",
system_prompt: "Return concise findings with file paths."
)
]
)
This explicit configuration is the supported path until capability profiles are wired as a first-class automatic overlay.
Provider Profiles
BeamWeaver.Agent.ProviderProfile is the active companion API for model-construction defaults. It applies when an agent is built from a binary or atom model identifier:
alias BeamWeaver.Agent.ProviderProfile
:ok =
ProviderProfile.register_provider_profile(
"openai",
ProviderProfile.new(init_kwargs: [temperature: 0])
)
:ok =
ProviderProfile.register_provider_profile(
"openai:gpt-5.4",
ProviderProfile.new(init_kwargs: [reasoning_effort: :medium])
)
{:ok, agent} =
BeamWeaver.Agent.build(
model: "openai:gpt-5.4",
tools: []
)
Provider-level and exact-model profiles merge at resolution time. Caller-supplied model options still win:
{:ok, agent} =
BeamWeaver.Agent.build(
model: "openai:gpt-5.4",
model_opts: [temperature: 0.2]
)
Provider profiles support:
| Field | Meaning |
|---|---|
:init_kwargs
| Static options forwarded to model initialization. |
:model_opts
| Compatibility alias for model-construction options. |
:init_kwargs_factory
| Zero-arity function that returns runtime-derived options. |
:pre_init
| One-arity function called with the model spec before construction. |
Factories merge by running both and merging their results; pre_init callbacks chain in registration order. BeamWeaver includes a built-in "openai" provider profile that sets use_responses_api: true for agent model strings.
Passing a preconfigured model struct bypasses provider profiles because the model has already been initialized:
model =
BeamWeaver.Models.init_chat_model!("openai:gpt-5.4",
temperature: 0.2
)
{:ok, agent} = BeamWeaver.Agent.build(model: model, tools: [])
Model Profiles
Model profiles are not Deep Agents capability profiles. They are BeamWeaver's provider capability records:
{:ok, model} = BeamWeaver.Models.init_chat_model("openai:gpt-5.4")
model.profile.max_input_tokens
BeamWeaver.Models.Profile.supports?(model.profile, :tool_calling)
BeamWeaver.Models.Profile.supports?(model.profile, :structured_output)
The agent and provider layers use model profiles to make capability decisions: structured output strategy selection, context-window checks, summarization thresholds, supported parameter validation, modality support, and tokenizer selection.
Inspect checked-in model profiles:
mix beam_weaver.models.profiles
mix beam_weaver.models.profiles --provider openai --json
mix beam_weaver.models.profiles --provider anthropic --json
Override missing or stale model capability data explicitly:
{:ok, model} =
BeamWeaver.Models.init_chat_model("openai:future-model",
profile: %{
max_input_tokens: 200_000,
tool_calling: true,
structured_output: true,
streaming: true
}
)
Official Docs Differences
When porting from the Python Deep Agents profile page:
| Official Deep Agents term | BeamWeaver term |
|---|---|
HarnessProfile
|
BeamWeaver.Agent.CapabilityProfile
|
HarnessProfileConfig
|
BeamWeaver.Agent.CapabilityProfileConfig
|
ProviderProfile
|
BeamWeaver.Agent.ProviderProfile
|
GeneralPurposeSubagentProfile
|
BeamWeaver.Agent.GeneralPurposeSubagentProfile
|
Important differences:
-
Capability profiles are not automatically applied by
BeamWeaver.Agent.build(...)oruse BeamWeaver.Agent; use direct agent options for runtime behavior. -
Python
importlib.metadataentry points for profile plugins are not a BeamWeaver API. Register profiles from normal application startup code. -
Python
module:Classstring imports for excluded middleware are not supported. Use middleware modules or public middleware names in trusted Elixir config. -
There is no automatic default
general-purposesubagent in normal agent builds. Configure explicit subagents instead. -
There is no wildcard profile key for all providers.
-
Model profiles are a separate capability-metadata layer and should not be confused with provider profiles or capability profiles.