huggingface/smolagents · error · AttributeError

The 'system_prompt' property is read-only. Use 'self.prompt_

Error message

The 'system_prompt' property is read-only. Use 'self.prompt_templates["system_prompt"]' instead.

What it means

smolagents agents expose a read-only system_prompt property computed from the prompt_templates each time. Assigning agent.system_prompt = '...' raises AttributeError because the stored template would silently diverge from the computed prompt.

Source

Thrown at src/smolagents/agents.py:360

        self.task: str | None = None
        self.memory = AgentMemory(self.system_prompt)

        if logger is None:
            self.logger = AgentLogger(level=verbosity_level)
        else:
            self.logger = logger

        self.monitor = Monitor(self.model, self.logger)
        self._setup_step_callbacks(step_callbacks)
        self.stream_outputs = False

    @property
    def system_prompt(self) -> str:
        return self.initialize_system_prompt()

    @system_prompt.setter
    def system_prompt(self, value: str):
        raise AttributeError(
            """The 'system_prompt' property is read-only. Use 'self.prompt_templates["system_prompt"]' instead."""
        )

    def _validate_name(self, name: str | None) -> str | None:
        if name is not None and not is_valid_name(name):
            raise ValueError(f"Agent name '{name}' must be a valid Python identifier and not a reserved keyword.")
        return name

    def _setup_managed_agents(self, managed_agents: list | None = None) -> None:
        """Setup managed agents with proper logging."""
        self.managed_agents = {}
        if managed_agents:
            assert all(agent.name and agent.description for agent in managed_agents), (
                "All managed agents need both a name and a description!"
            )
            self.managed_agents = {agent.name: agent for agent in managed_agents}
            # Ensure managed agents can be called as tools by the model: set their inputs and output_type
            for agent in self.managed_agents.values():

View on GitHub (pinned to 30bb116109)

Solutions

  1. Set the template instead: agent.prompt_templates['system_prompt'] = 'your new template' (Jinja2-renderable)
  2. Or pass prompt_templates={'system_prompt': ...} / system_prompt at construction time
  3. Note templates are rendered with variables (tool descriptions, authorized imports), so use Jinja placeholders where needed

Example fix

# before
agent.system_prompt = "You are a helpful assistant."

# after
agent.prompt_templates["system_prompt"] = "You are a helpful assistant. Tools: {{ tool_descriptions }}"
Defensive patterns

Strategy: validation

Validate before calling

def set_system_prompt(agent, template: str):
    agent.prompt_templates["system_prompt"] = template  # correct mutation point
    assert agent.system_prompt  # recompute/read works

Prevention

When it happens

Trigger: Executing agent.system_prompt = 'You are...' on any agent (ToolCallingAgent, CodeAgent, ManagedAgent); the setter always raises.

Common situations: Developers used to mutable prompt fields on other LLM frameworks try to tweak the system prompt after construction; attempting to customize a ManagedAgent's system prompt per-run by assignment.

Related errors


AI-assisted analysis of huggingface/smolagents@30bb116109 (2026-08-28). Data as JSON: /api/errors/71228c6b750ab8c2. Report an issue: GitHub.