# How FlaskAgent Implements the Delegation Pattern Using the `_parent` Attribute

> Discover how FlaskAgent implements the delegation pattern with its _parent attribute, enabling seamless attribute access and mutation for enhanced agent functionality. Learn more today.

- Repository: [Heurist/heurist-agent-framework](https://github.com/heurist-network/heurist-agent-framework)
- Tags: internals
- Published: 2026-03-03

---

**The `FlaskAgent` class in the heurist-agent-framework uses a protected `_parent` attribute combined with custom `__getattr__` and `__setattr__` methods to delegate all attribute access and mutation to a core agent when running in shared mode, or to itself when operating standalone.**

The delegation pattern in the `heurist-network/heurist-agent-framework` allows the Flask-based API interface to flexibly wrap an existing agent or operate independently. At the heart of this implementation is the `_parent` attribute within the `FlaskAgent` class, which determines whether attribute operations are handled locally or forwarded to a core agent.

## Initializing the `_parent` Attribute in [`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py)

The delegation mechanism begins in the `FlaskAgent` constructor located in [`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py) (lines 28‑39). The initialization logic distinguishes between **shared mode** (wrapping an existing agent) and **standalone mode** (self-contained operation).

```python
class FlaskAgent:
    def __init__(self, core_agent=None):
        # …

        if core_agent:
            super().__setattr__("_parent", core_agent)      # ← delegate to provided core

        else:
            # Stand‑alone mode – the agent is its own parent

            super().__setattr__("_parent", self)            # bypass __setattr__

            super().__init__()

```

When a **core agent** (an instance of `BaseAgent`) is supplied, `FlaskAgent` stores it in `_parent`. If no core is supplied, the agent sets `_parent` to **itself** and then runs the normal `BaseAgent` constructor. The use of `super().__setattr__` avoids invoking the overridden `__setattr__` during this bootstrap phase, preventing infinite recursion.

## Delegating Attribute Reads via `__getattr__`

Attribute read delegation is handled by a custom `__getattr__` method defined in [`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py) (lines 46‑48). This method is invoked automatically whenever an attribute lookup fails to find the named attribute in the instance dictionary.

```python
def __getattr__(self, name):
    # missing attribute → forward to parent

    return getattr(self._parent, name)

```

The implementation simply forwards the lookup to whatever object lives in `_parent`. This gives the FlaskAgent seamless access to the core agent’s methods and properties without explicit proxy methods for every attribute.

## Delegating Attribute Writes via `__setattr__`

Attribute mutation follows a more complex delegation logic in `__setattr__` ([`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py), lines 50‑59). The method must distinguish between initialization-time assignments, local attribute updates, and delegated writes.

```python
def __setattr__(self, name, value):
    if not hasattr(self, "_parent"):
        # still constructing – set locally

        super().__setattr__(name, value)
    elif name == "_parent" or self is self._parent or name in self.__dict__:
        # set on this instance (e.g., _parent itself or already‑existing attrs)

        super().__setattr__(name, value)
    else:
        # forward the assignment to the parent

        setattr(self._parent, name, value)

```

The logic follows three branches:

1. **Construction phase**: If `_parent` does not yet exist, the assignment is handled locally using `super().__setattr__`.
2. **Local updates**: Assignments to `_parent` itself, attributes already present in `__dict__`, or when the agent is its own parent (`self is self._parent`) are stored on the instance.
3. **Delegation**: All other assignments are forwarded to the parent object, ensuring that state changes affect the core agent when running in shared mode.

## Detecting Shared vs. Standalone Mode at Runtime

The `FlaskAgent` uses the `_parent` reference to determine its operating mode during request handling ([`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py), lines 95‑99).

```python
if self._parent != self:
    logger.info("Operating in shared mode with core agent")
else:
    logger.info("Operating in standalone mode")

```

By comparing `self._parent` to `self`, the agent can branch logic appropriately, choosing whether to invoke methods on the wrapped core or on its own `BaseAgent` infrastructure.

## Practical Usage Examples

The following patterns demonstrate how to instantiate and use `FlaskAgent` in both configurations:

```python

# 1️⃣ Stand‑alone usage – no core supplied

flask_agent = FlaskAgent()
assert flask_agent._parent is flask_agent   # self‑parented

# 2️⃣ Shared usage – delegate to an existing core agent

core = BaseAgent()
flask_agent = FlaskAgent(core_agent=core)
assert flask_agent._parent is core          # delegated

# 3️⃣ Attribute delegation

flask_agent.some_core_method()   # __getattr__ forwards call to core

flask_agent.shared_state = 42    # __setattr__ stores on core when not local

```

## Summary

- **`_parent`** serves as the delegation pivot, storing either a supplied core agent or a self-reference.
- **Initialization** in [`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py) uses `super().__setattr__` to bootstrap the `_parent` reference without triggering recursion.
- **Read delegation** occurs via `__getattr__`, which forwards missing attribute lookups to `_parent`.
- **Write delegation** in `__setattr__` distinguishes between construction, local updates, and forwarded assignments to ensure state consistency.
- **Mode detection** compares `self._parent` to `self` to determine whether the agent is wrapping a shared core or operating standalone.

## Frequently Asked Questions

### What is the purpose of the `_parent` attribute in FlaskAgent?

The `_parent` attribute stores a reference to the **core agent** instance when `FlaskAgent` is initialized with an existing agent, or points to `self` when operating in standalone mode. This reference enables the delegation mechanism by providing a target for `__getattr__` and `__setattr__` operations.

### How does FlaskAgent handle attribute assignment when running in shared mode?

When running in shared mode, the custom `__setattr__` method checks if the attribute already exists locally or if the assignment targets `_parent` itself. If neither condition is met, the assignment is forwarded via `setattr(self._parent, name, value)`, ensuring that state changes affect the wrapped core agent rather than the Flask wrapper.

### Can FlaskAgent operate without a core agent?

Yes. When instantiated without a `core_agent` argument, `FlaskAgent` sets `_parent` to `self` and invokes `super().__init__()`, initializing its own `BaseAgent` infrastructure. This allows the class to function as a self-contained agent while maintaining the same interface used in shared mode.

### Where is the delegation logic implemented in the heurist-agent-framework?

The delegation logic is implemented in [`interfaces/api.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/interfaces/api.py) within the `FlaskAgent` class. The relevant methods—`__init__`, `__getattr__`, and `__setattr__`—appear between lines 28 and 59, while runtime mode detection occurs around lines 95-99. The core agent type, `BaseAgent`, is defined in [`agents/base_agent.py`](https://github.com/heurist-network/heurist-agent-framework/blob/main/agents/base_agent.py).