rohitg00/ai-engineering-from-scratch · error · ValueError

unknown performative

Error message

unknown performative: {self.performative}

What it means

Constructor guard on ACLMessage.__post_init__: the message's performative is not in the FIPA ACL performative set (inform, request, subscribe, cancel, failure, ...). Because the performative drives how the message renders and is interpreted, an unknown one is rejected at construction time rather than downstream.

Solutions

  1. Use one of the constants from the PERFORMATIVES set
  2. Check for typos and case — the set is lowercase and exact
  3. Extend PERFORMATIVES deliberately if modeling additional FIPA communicative acts
  4. Validate agent-generated performatives before constructing ACLMessage instances
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at phases/16-multi-agent-and-swarms/02-fipa-acl-heritage/code/main.py:36 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/95ba04a7750edf7d. Report an issue: GitHub.

Appendix: source

Thrown at phases/16-multi-agent-and-swarms/02-fipa-acl-heritage/code/main.py:36

    "subscribe", "cancel", "failure",
}


@dataclass
class ACLMessage:
    performative: str
    sender: str
    receiver: str
    content: Any
    language: str = "SL0"
    ontology: str = "default"
    protocol: Optional[str] = None
    conversation_id: Optional[str] = None
    reply_with: Optional[str] = None

    def __post_init__(self) -> None:
        if self.performative not in PERFORMATIVES:
            raise ValueError(f"unknown performative: {self.performative}")

    def render(self) -> str:
        fields = [
            f":sender       {self.sender}",
            f":receiver     {self.receiver}",
            f":content      {self.content!r}",
            f":language     {self.language}",
            f":ontology     {self.ontology}",
        ]
        if self.protocol:
            fields.append(f":protocol     {self.protocol}")
        if self.conversation_id:
            fields.append(f":conversation-id {self.conversation_id}")
        if self.reply_with:
            fields.append(f":reply-with   {self.reply_with}")
        inner = "\n  ".join(fields)
        return f"({self.performative}\n  {inner}\n)"

View on GitHub (pinned to 39ea8a1c6d)