Despite the hype surrounding “AI agents” and the pressure that accompanies the trend, they meaningfully extend the contemporary programming paradigm and, in doing so, expand what working programmers can reasonably build. While constructing the foundational—almost skeletal—codebase for my bots, I found myself reconsidering several design choices, especially in the following areas:

  • Data system architecture. The realization that I’m not confined to the typical constraints of day-to-day data work—merely modeling or drafting how datasets are collected and stored—has been genuinely invigorating.
  • The importance of logging and tracing. Put differently, they force me to quantify how far I push “decorative” functions and classes. There’s a fine line between adequate structure and over-engineering—and, more often than I’d like, I end up on the wrong side of it.

From User Event Driven Point-of-view

The workflow is as follows:

sequenceDiagram
    autonumber
    actor User

    participant SC as SessionController
    participant LLM as GoogleGenAIProvider
    participant Cortex as AgentCortex
    participant DD as DataDiscovery
    participant Skel as SkeletonAgentPipeline
    participant Plan as Planner
    participant Exec as Executioner
    participant Eval as Evaluator

    User->>SC: new SessionController(dataset, **llm_kwargs)
    SC->>LLM: construct provider(**llm_kwargs)
    SC->>Cortex: construct AgentCortex()
    SC-->>User: controller ready

    User->>SC: execute_pipeline(**kwargs)

    loop for each stage in SessionController (e.g. discovery, modeller, transformer)
        SC->>DD: execute_pipeline(llm=LLM, skele=Skel, **kwargs)

        %% DataDiscovery first runs its own stages (e.g. Profiler),
        %% then delegates to the SkeletonAgentPipeline
        DD->>Skel: execute_pipeline(llm=LLM, objective=derived_objective, **kwargs)

        %% Planner
        Skel->>Plan: call (llm=LLM, objective)
        Plan-->>Skel: plannerResult (steps)

        %% Executioner (per step)
        loop for step in plannerResult.steps
            Skel->>Exec: call (llm=LLM, current_step=step)
            Exec-->>Skel: execResult
        end

        %% Evaluator
        Skel->>Eval: call (llm=LLM, results=all execResult)
        Eval-->>Skel: evaluationResult

        Skel-->>DD: skeletonTraces (planner, executor[], evaluator)
        DD-->>SC: stageState, skeletonTraces

        SC->>Cortex: agent.update(stageState, fieldPattern=stage_name)
    end

    SC-->>User: all traces and final state