Skip to main content

Agent settings

A ready-to-run example is available here.

FaheemCodeAgentSettings gives you a structured, serializable way to define an agent's model, tools, and optional subsystems like the condenser. Use it when you want to store agent configuration in JSON, send it over an API, or rebuild agents from validated settings later.

Why use agent settings

  • Keep agent configuration as data instead of wiring everything together imperatively.
  • Validate settings with Pydantic before creating an agent.
  • Serialize and deserialize settings for storage, transport, or UI-driven configuration.
  • Create different agent variants by changing only the settings payload.

Build settings

Create an FaheemCodeAgentSettings object with the same ingredients you would normally pass to an Agent.

from pydantic import SecretStr

from faheemcode.sdk import LLM, Tool
from faheemcode.sdk.settings import CondenserSettings, FaheemCodeAgentSettings
from faheemcode.tools.file_editor import FileEditorTool
from faheemcode.tools.terminal import TerminalTool

settings = FaheemCodeAgentSettings(
llm=LLM(
model="anthropic/claude-sonnet-4-5-20250929",
api_key=SecretStr("your-api-key"),
),
tools=[
Tool(name=TerminalTool.name),
Tool(name=FileEditorTool.name),
],
condenser=CondenserSettings(enabled=True, max_size=50),
)

Serialize and restore settings

Because FaheemCodeAgentSettings is a Pydantic model, you can dump it to JSON-compatible data and restore it later.

payload = settings.model_dump(mode="json")
restored = FaheemCodeAgentSettings.model_validate(payload)

This is useful when:

  • Saving agent configuration in a database
  • Sending settings through an API
  • Letting users edit agent configuration in a form-based UI
  • Rehydrating the same agent setup in another process

Load persisted settings

model_validate only accepts payloads that already match the current schema. Use from_persisted for data written by an older SDK version: it applies the registered schema migrations first, then validates the migrated payload against the class you call it on.

restored = FaheemCodeAgentSettings.from_persisted(payload)

from_persisted is defined on AgentSettingsBase, so it is a concrete-variant loader: FaheemCodeAgentSettings.from_persisted() returns an FaheemCodeAgentSettings and ACPAgentSettings.from_persisted() returns an ACPAgentSettings. When you do not know which variant a payload holds, use validate_agent_settings (also in faheemcode.sdk.settings) instead — it dispatches across the settings union.

Passing an already-validated instance of that variant returns it unchanged, so its secrets are preserved without a lossy serialization round trip.

Encrypted payloads

Secret-bearing fields only decrypt when you pass the same validation context that was used to write them.

persisted = settings.model_dump(mode="json", context={"cipher": cipher})
restored = FaheemCodeAgentSettings.from_persisted(persisted, context={"cipher": cipher})

Errors

ExceptionRaised when
TypeErrorThe payload is not a mapping or BaseModel, or its schema_version is not an integer.
ValueErrorschema_version is negative, newer than the supported version, or has no registered migration.
pydantic.ValidationErrorThe migrated payload is invalid for the class you called from_persisted on.

Create an agent from settings

Once validated, create a working agent directly from the settings object.

agent = settings.create_agent()

You can then pass that agent into a Conversation, or derive another agent by changing the settings payload. For example, the full example below also shows how removing FileEditorTool and disabling the condenser produces a different agent configuration without rewriting the rest of the setup.

Ready-to-run example

"""Create, serialize, and deserialize FaheemCodeAgentSettings, then build an agent.

Demonstrates:
1. Configuring an agent entirely through FaheemCodeAgentSettings (LLM, tools, condenser).
2. Serializing settings to JSON and restoring them.
3. Building an Agent from settings via ``create_agent()``.
4. Running a short conversation to prove the settings take effect.
5. Changing the tool list and showing the agent's capabilities change.
"""

import json
import os

from pydantic import SecretStr

from faheemcode.sdk import LLM, Conversation, FaheemCodeAgentSettings, Tool
from faheemcode.sdk.settings import CondenserSettings
from faheemcode.tools.file_editor import FileEditorTool
from faheemcode.tools.terminal import TerminalTool

# ── 1. Build settings ────────────────────────────────────────────────────
api_key = os.getenv("LLM_API_KEY")
assert api_key is not None, "LLM_API_KEY environment variable is not set."

settings = FaheemCodeAgentSettings(
llm=LLM(
model=os.getenv("LLM_MODEL", "anthropic/claude-sonnet-4-5-20250929"),
api_key=SecretStr(api_key),
base_url=os.getenv("LLM_BASE_URL"),
),
tools=[
Tool(name=TerminalTool.name),
Tool(name=FileEditorTool.name),
],
condenser=CondenserSettings(enabled=True, max_size=50),
)

# ── 2. Serialize → JSON → deserialize ────────────────────────────────────
payload = settings.model_dump(mode="json")
print("Serialized settings (JSON):")
print(json.dumps(payload, indent=2, default=str)[:800], "…")
print()

restored = FaheemCodeAgentSettings.model_validate(payload)
assert restored.condenser.enabled is True
assert restored.condenser.max_size == 50
assert len(restored.tools) == 2
print("✓ Roundtrip deserialization successful — all fields preserved")
print()

# ── 3. Create agent from settings and run a task ─────────────────────────
agent = settings.create_agent()
print(f"Agent created: llm.model={agent.llm.model}")
print(f" tools={[t.name for t in agent.tools]}")
print(f" condenser={type(agent.condenser).__name__}")
print()

cwd = os.getcwd()
conversation = Conversation(agent=agent, workspace=cwd)
conversation.send_message(
"Create a file called hello_settings.txt containing "
"'Agent settings work!' then confirm the file exists with ls."
)
conversation.run()

# Verify the agent actually wrote the file
assert os.path.exists(os.path.join(cwd, "hello_settings.txt")), (
"Agent should have created hello_settings.txt"
)
print("✓ Agent created hello_settings.txt — settings drove real behavior")
print()

# ── 4. Different settings → different behavior ───────────────────────────
# Now create settings with ONLY the terminal tool and condenser disabled.
terminal_only_settings = FaheemCodeAgentSettings(
llm=settings.llm,
tools=[Tool(name=TerminalTool.name)],
condenser=CondenserSettings(enabled=False),
)

terminal_agent = terminal_only_settings.create_agent()
print(f"Terminal-only agent tools: {[t.name for t in terminal_agent.tools]}")
assert len(terminal_agent.tools) == 1
assert terminal_agent.condenser is None # condenser disabled in these settings
print("✓ Different settings produce different agent configuration")
print()

# ── Cleanup ──────────────────────────────────────────────────────────────
os.remove(os.path.join(cwd, "hello_settings.txt"))

# Report cost
cost = conversation.conversation_stats.get_combined_metrics().accumulated_cost
print(f"\nEXAMPLE_COST: {cost}")

You can run the example code as-is.

Bring your own provider key
export LLM_API_KEY="your-api-key"
export LLM_MODEL="anthropic/claude-sonnet-4-5-20250929" # or openai/gpt-4o, etc.
cd software-agent-sdk
uv run python examples/01_standalone_sdk/46_agent_settings.py
Faheem Code Cloud key
# https://app.faheemcode.ai/settings/api-keys
export LLM_API_KEY="example-user-api-key"
export LLM_MODEL="faheemcode/claude-sonnet-4-5-20250929"
cd software-agent-sdk
uv run python examples/01_standalone_sdk/46_agent_settings.py

Next steps