Files
cleveragents-core/docs/reference/resource_dag.md

4.5 KiB

Resource DAG

Resources in CleverAgents form a directed acyclic graph (DAG) where parent resources contain or reference child resources. This document describes the linking rules, cycle detection, type compatibility enforcement, and auto-discovery behaviour.

DAG Rules

Rule Description
No self-loops A resource cannot be its own child.
No cycles If resource A is an ancestor of B, then B cannot become a parent of A.
Type compatibility The child's resource type must appear in the parent type's child_types list.
Unique links A given (parent, child) pair can only be linked once.
Both must exist Both the parent and the child resource must be registered before linking.

API

Links a child resource to a parent in the DAG.

  1. Validates that both resources exist in the registry.
  2. Checks type compatibility — the child resource's type must be listed in the parent resource type's child_types field.
  3. Performs cycle detection — walks the ancestor chain of the parent to ensure the child is not already an ancestor.
  4. Persists the link in the resource_links table.

Errors:

  • ResourceNotFoundRepoError — parent or child does not exist.
  • TypeIncompatibleError — child type not in parent's child_types.
  • CycleDetectedError — linking would create a cycle.
  • DuplicateResourceLinkError — link already exists.

Removes a parent-child link from the DAG.

  1. Validates that both resources exist.
  2. Validates the link exists.
  3. Deletes the link from resource_links.

Errors:

  • ResourceNotFoundRepoError — parent or child does not exist.
  • LinkNotFoundError — the link does not exist.

get_children(resource_id)

Returns all direct children of a resource (via resource_links).

get_parents(resource_id)

Returns all direct parents of a resource (via resource_links).

Cycle Detection

Cycle detection uses a breadth-first search upward through the resource_links table starting from the proposed parent. If the proposed child is found among the ancestors, the link is rejected with a CycleDetectedError that includes the cycle path.

Example

A -> B -> C

Attempting to link C -> A would be rejected because A is an ancestor of C. The error message includes the path: A -> B -> C -> A.

Type Compatibility

Each resource type defines a child_types list of allowed child type names. When linking, the system verifies:

child.resource_type_name in parent_type.child_types

If the parent type's child_types list is empty, any child type is allowed (no restriction).

Example

# git-checkout type
child_types: ["fs-directory", "git"]

Only resources of type fs-directory or git can be linked as children of a git-checkout resource.

Auto-Discovery

auto_discover_children(resource_id)

Materializes child resources based on the parent's type auto-discovery configuration.

  1. Looks up the resource and its type.
  2. Reads the auto_discovery configuration from the type.
  3. For each discovery rule where enabled is true:
    • Checks the child type exists in the database.
    • Checks type compatibility with the parent.
    • Creates a new child resource with auto_discovered = true.
    • Links the child to the parent via resource_links.
  4. Returns the list of newly created child resources.

Auto-Discovery Configuration

Auto-discovery is configured per resource type in YAML:

auto_discovery:
  enabled: true
  rules:
    - type: fs-directory
      pattern: "*/"
    - type: fs-file
      pattern: "*"

Each rule specifies:

  • type — the child resource type name to create.
  • pattern — a glob pattern (used by handlers for actual file discovery; the repository layer creates placeholder entries).

When Does Auto-Discovery Run?

Auto-discovery is triggered by calling auto_discover_children(resource_id). This is typically invoked:

  • When a resource is first registered.
  • When a resource's contents change (e.g., new files appear).
  • On demand via CLI commands.

Database Schema

Column Type Description
parent_id String(26) FK to resources.resource_id
child_id String(26) FK to resources.resource_id
created_at String(30) ISO-8601 timestamp

Primary key: (parent_id, child_id)

Constraints:

  • parent_id != child_id (no self-loops)
  • Foreign keys cascade on delete