2025, Dec 23 23:00

How to Resolve NameError: Agent When Importing AIMA Agents in Python (module vs from import)

Get rid of NameError: Agent when using the AIMA agents module. Learn the difference between importing a module and importing names, with examples and fixes.

When you start wiring a small Python script around the AIMA agents module, it’s easy to assume that importing the module automatically exposes its contents in your local namespace. That assumption leads straight to a NameError at class definition time, even though the module import itself looks fine and diagnostic prints confirm everything is on sys.path.

Reproducible setup

The snippet below loads the parent folder onto sys.path, imports the AIMA agents module, prints a couple of checks, and then tries to subclass Agent. The module import works, but the class name isn’t available in the current scope.

import os
import sys
# Resolve the parent folder of this file
root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
print(f"Parent dir is {root_dir}")
# Prepend the parent folder to sys.path
sys.path.insert(0, root_dir)
print(f"Sys path is {sys.path}")
# Bring in the AIMA agents module
import agents
print("Successfully imported agents from AIMA library")
print("agents module:", agents)
print("Has TrivialVacuumEnvironment:", hasattr(agents, "TrivialVacuumEnvironment"))
# Attempt to subclass Agent from agents
class SightlessHound(Agent):
    def eat(self, item):
        print("Dog: Ate food at {}.".format(self.location))
    def drink(self, item):
        print("Dog: Drank water at {}.".format(self.location))
pup = SightlessHound()

Why the error happens

In Python, import agents binds only the module object to the name agents. It does not inject the names defined inside that module into your current namespace. That’s why Agent is unknown at the point where the class is defined. Your checks show the module is present and accessible, and even confirm that certain attributes exist on it. The failure occurs specifically because the class name Agent wasn’t imported into the local scope.

In other words, after import agents you need to either refer to the class with a module qualifier (agents.Agent) or explicitly import the class name from the module.

Fix

Make Agent available in the local namespace with an explicit import after import agents. The rest of the logic remains the same.

import os
import sys
# Resolve the parent folder of this file
root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
print(f"Parent dir is {root_dir}")
# Prepend the parent folder to sys.path
sys.path.insert(0, root_dir)
print(f"Sys path is {sys.path}")
# Bring in the AIMA agents module
import agents
from agents import Agent  # make Agent visible in this namespace
print("Successfully imported agents from AIMA library")
print("agents module:", agents)
print("Has TrivialVacuumEnvironment:", hasattr(agents, "TrivialVacuumEnvironment"))
# Now the subclass can resolve Agent correctly
class SightlessHound(Agent):
    def eat(self, item):
        print("Dog: Ate food at {}.".format(self.location))
    def drink(self, item):
        print("Dog: Drank water at {}.".format(self.location))
pup = SightlessHound()

Alternatively, keep only import agents and qualify the name where it’s used by writing class SightlessHound(agents.Agent):. This follows the same rule of explicitly accessing names through the module object.

Why this matters

Understanding how Python’s import mechanism maps names prevents subtle failures that surface only when the runtime hits a class or function definition. Diagnostics like printing sys.path or checking hasattr on the module are useful, but they validate location and loading, not name resolution in your current scope. Keeping a clear distinction between importing a module and importing names from that module makes code more predictable and easier to move across environments.

Takeaways

If you import a module, reference its contents with the module prefix. If you need a specific symbol directly, import it explicitly. Both approaches are valid; choose the one that keeps your code straightforward and readable in your context.