Skip to content

Frontend Dashboard

The AGENT-K frontend provides a real-time mission monitoring dashboard built with Next.js, featuring live updates via the AG-UI protocol.

Architecture

graph TB
    subgraph Frontend
        D[Dashboard] --> PV[Plan View]
        D --> EV[Evolution View]
        D --> RV[Research View]
        D --> MV[Memory View]
        D --> LV[Logs View]
    end

    subgraph Backend
        API[FastAPI] --> SSE[SSE Stream]
    end

    SSE --> D

Components

Mission Dashboard

The main dashboard component orchestrating all views:

// frontend/components/agent-k/mission-dashboard.tsx
import { useAgentKState } from '@/hooks/use-agent-k-state';

export function MissionDashboard() {
  const { state, events, connected } = useAgentKState();

  return (
    <div className="grid grid-cols-12 gap-4">
      <div className="col-span-3">
        <PlanView phases={state.phases} currentPhase={state.currentPhase} />
      </div>
      <div className="col-span-6">
        <MainView phase={state.currentPhase} data={state} />
      </div>
      <div className="col-span-3">
        <ToolCallsView calls={state.toolCalls} />
      </div>
    </div>
  );
}

Plan View

Shows mission phases and progress:

// frontend/components/agent-k/plan-view.tsx
interface Phase {
  id: string;
  name: string;
  status: 'pending' | 'in_progress' | 'complete' | 'failed';
  tasks: Task[];
}

export function PlanView({ phases, currentPhase }: PlanViewProps) {
  return (
    <div className="space-y-4">
      <h2 className="text-lg font-semibold">Mission Plan</h2>
      {phases.map((phase) => (
        <PhaseCard
          key={phase.id}
          phase={phase}
          isCurrent={phase.id === currentPhase}
        />
      ))}
    </div>
  );
}

Evolution View

Displays fitness charts during optimization:

// frontend/components/agent-k/evolution-view.tsx
import { LineChart, Line, XAxis, YAxis, Tooltip } from 'recharts';

export function EvolutionView({ history }: EvolutionViewProps) {
  return (
    <div>
      <h2 className="text-lg font-semibold">Evolution Progress</h2>
      <LineChart width={600} height={300} data={history}>
        <XAxis dataKey="generation" />
        <YAxis domain={[0, 1]} />
        <Line
          type="monotone"
          dataKey="bestFitness"
          stroke="#8884d8"
          name="Best"
        />
        <Line
          type="monotone"
          dataKey="meanFitness"
          stroke="#82ca9d"
          name="Mean"
        />
        <Tooltip />
      </LineChart>

      <div className="mt-4 grid grid-cols-3 gap-4">
        <Stat label="Generation" value={history.at(-1)?.generation} />
        <Stat label="Best Fitness" value={history.at(-1)?.bestFitness} />
        <Stat label="Evaluations" value={history.at(-1)?.evaluations} />
      </div>
    </div>
  );
}

Research View

Shows findings from the SCIENTIST:

// frontend/components/agent-k/research-view.tsx
export function ResearchView({ findings }: ResearchViewProps) {
  return (
    <div className="space-y-6">
      <LeaderboardAnalysis analysis={findings.leaderboardAnalysis} />

      <section>
        <h3 className="font-semibold">Strategy Recommendations</h3>
        <ul className="list-disc list-inside">
          {findings.strategyRecommendations.map((rec, i) => (
            <li key={i}>{rec}</li>
          ))}
        </ul>
      </section>

      <section>
        <h3 className="font-semibold">Papers Found</h3>
        <PaperList papers={findings.papers} />
      </section>
    </div>
  );
}

Memory View

Shows persistent data across agents:

// frontend/components/agent-k/memory-view.tsx
export function MemoryView({ memory }: MemoryViewProps) {
  return (
    <div>
      <h2 className="text-lg font-semibold">Mission Memory</h2>
      <div className="space-y-2">
        {Object.entries(memory).map(([key, value]) => (
          <MemoryEntry key={key} keyName={key} value={value} />
        ))}
      </div>
    </div>
  );
}

Logs View

Real-time agent activity:

// frontend/components/agent-k/logs-view.tsx
export function LogsView({ logs }: LogsViewProps) {
  return (
    <div className="font-mono text-sm">
      <h2 className="text-lg font-semibold font-sans">Activity Log</h2>
      <div className="h-96 overflow-y-auto bg-gray-900 p-4 rounded">
        {logs.map((log, i) => (
          <LogEntry key={i} entry={log} />
        ))}
      </div>
    </div>
  );
}

State Management

useAgentKState Hook

// frontend/hooks/use-agent-k-state.tsx
import { useEffect, useReducer } from 'react';

interface MissionState {
  missionId: string | null;
  currentPhase: string | null;
  phases: Phase[];
  evolution: EvolutionState | null;
  research: ResearchFindings | null;
  memory: Record<string, unknown>;
  toolCalls: ToolCall[];
  logs: LogEntry[];
}

export function useAgentKState(missionId?: string) {
  const [state, dispatch] = useReducer(missionReducer, initialState);

  useEffect(() => {
    if (!missionId) return;

    const eventSource = new EventSource(
      `${API_URL}/mission/${missionId}/events`
    );

    eventSource.onmessage = (e) => {
      const event = JSON.parse(e.data);
      dispatch({ type: 'EVENT_RECEIVED', event });
    };

    return () => eventSource.close();
  }, [missionId]);

  return state;
}

Reducer

function missionReducer(state: MissionState, action: Action): MissionState {
  switch (action.type) {
    case 'EVENT_RECEIVED':
      return processEvent(state, action.event);
    case 'RESET':
      return initialState;
    default:
      return state;
  }
}

function processEvent(state: MissionState, event: AgentEvent): MissionState {
  // Process different event types
  switch (event.type) {
    case 'phase-start':
      return updatePhase(state, event.data);
    case 'generation-complete':
      return updateEvolution(state, event.data);
    case 'tool-start':
      return addToolCall(state, event.data);
    // ...
  }
}

Styling

Tailwind Configuration

// frontend/tailwind.config.ts
export default {
  theme: {
    extend: {
      colors: {
        'agent-k': {
          primary: '#7c3aed',
          secondary: '#fbbf24',
          background: '#0f172a',
        },
      },
    },
  },
};

Phase Status Colors

const statusColors = {
  pending: 'bg-gray-500',
  in_progress: 'bg-blue-500 animate-pulse',
  complete: 'bg-green-500',
  failed: 'bg-red-500',
};

Running the Dashboard

Development

cd frontend
pnpm install
pnpm dev

Dashboard runs at http://localhost:3000.

Production

pnpm build
pnpm start

Environment Configuration

# frontend/.env.local
NEXT_PUBLIC_API_URL=http://localhost:9000
AUTH_SECRET=your-secret-key

Integration with Backend

Ensure the backend is running:

cd backend
source .venv/bin/activate
python -m agent_k.ui.agui

Or start both with:

./run.sh

Component Structure

frontend/components/agent-k/
├── mission-dashboard.tsx     # Main dashboard
├── plan-view.tsx             # Phase/task display
├── evolution-view.tsx        # Fitness charts
├── research-view.tsx         # SCIENTIST findings
├── memory-view.tsx           # Cross-agent memory
├── logs-view.tsx             # Activity log
├── tool-calls-view.tsx       # Tool call display
├── phase-card.tsx            # Individual phase card
├── task-item.tsx             # Individual task item
├── stat.tsx                  # Statistic display
└── connection-status.tsx     # SSE connection indicator

Next Steps