# How to Check if an AgentSession Is Currently Running in Pi-Web

> Learn how to check if an AgentSession is running in pi-web. Explore REST API checks, in-process methods, and real-time broadcast subscriptions for efficient status monitoring.

- Repository: [Alex Yang/pi-web](https://github.com/agegr/pi-web)
- Tags: how-to-guide
- Published: 2026-07-23

---

**You can verify an AgentSession's execution status via the REST API endpoint `GET /api/agent/[id]/state`, inspect the in-process `AgentSessionWrapper.isRunning()` method, or subscribe to real-time updates using the global broadcast mechanism.**

The **pi-web** repository provides three distinct mechanisms to determine whether an AgentSession is actively processing prompts or executing tasks. Depending on your architecture—whether you're integrating with the Next.js backend, debugging internal Node.js state, or building a React frontend—you can access real-time execution status through specific endpoints and wrapper methods.

## Server-Side API Endpoint

The primary HTTP interface for checking session status resides in **`app/api/agent/[id]/state/route.ts`**. This Next.js API route returns a JSON payload containing a boolean `running` flag and detailed state information.

The handler validates the session through the RPC wrapper's `isAlive()` method before reporting the status. When the session exists and the RPC connection is active, the endpoint returns `running: true` if the agent is currently processing.

```json
{
  "running": true,
  "state": { ... }
}

```

```typescript
// Server-side check (Node/Next.js)
import fetch from 'node-fetch';

async function isSessionRunning(sessionId: string): Promise<boolean> {
  const res = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/agent/${sessionId}/state`);
  const { running } = await res.json();
  return running;
}

```

## In-Process Status Detection

For internal logic within the Node.js process, inspect the **`AgentSessionWrapper`** class defined in **[`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts)**. The `isRunning()` method (lines 39-41) aggregates multiple execution flags to determine if the session is busy.

According to the source code, `isRunning()` combines **`promptRunning`**, **`inner.isStreaming`**, **`inner.isCompacting`**, and **`inner.isBashRunning`**. When any of these flags are true, the session is considered active.

### Direct Registry Access

Access the global session registry to check status programmatically without HTTP overhead:

```typescript
import { getRegistry } from '@/lib/rpc-manager';

function logRunningSessions() {
  for (const [id, wrapper] of getRegistry()) {
    if (wrapper.isRunning()) {
      console.log(`Session ${id} is busy`);
    }
  }
}

```

## Real-Time Client Subscriptions

Frontend components receive live updates through two mechanisms in **[`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts)**. The **`subscribeRunningSessions()`** function (lines 1010-1015) registers callbacks that receive arrays of currently running session IDs whenever the global state changes.

Additionally, the **Server-Sent Events (SSE)** endpoint **`GET /api/agent/running/events`** pushes updates whenever any session starts or stops running. The React frontend typically consumes this through the `useAgentSession` hook, though you can implement manual subscription for custom components (refer to **AGENTS.md** for the data flow diagram).

### React Hook Implementation

```tsx
import useSWR from 'swr';

function RunningIndicator({ sessionId }: { sessionId: string }) {
  const { data } = useSWR(
    `/api/agent/${sessionId}/state`,
    url => fetch(url).then(r => r.json())
  );

  if (!data) return null;
  return data.running ? '🟢 Agent is running' : '⚪️ Agent idle';
}

```

### Global Subscription Pattern

```typescript
import { subscribeRunningSessions } from '@/lib/rpc-manager';

const unsubscribe = subscribeRunningSessions((runningSessionIds) => {
  console.log('Currently running session IDs:', runningSessionIds);
});

// Cleanup when component unmounts or updates are no longer needed
unsubscribe();

```

## Practical Implementation Examples

When building integrations, choose the appropriate check based on your execution context:

- **Backend services**: Use the HTTP API endpoint for cross-process communication or `getRegistry()` for co-located checks
- **Internal debugging**: Call `wrapper.isRunning()` directly on the `AgentSessionWrapper` instance
- **React UI components**: Consume the SWR-based hook or subscribe to the SSE stream for real-time indicators

The three-tier architecture ensures you can check status from external services (REST), within the same Node process (direct method calls), or from browser clients (subscriptions).

## Summary

- **`GET /api/agent/[id]/state`** in `app/api/agent/[id]/state/route.ts` returns the canonical `running` boolean for HTTP clients
- **`AgentSessionWrapper.isRunning()`** in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) (lines 39-41) aggregates `promptRunning`, `isStreaming`, `isCompacting`, and `isBashRunning` flags for in-process checks
- **`subscribeRunningSessions()`** in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) (lines 1010-1015) provides a callback-based API for real-time updates in the frontend
- **`GET /api/agent/running/events`** exposes an SSE stream for push-based status monitoring

## Frequently Asked Questions

### What is the difference between `isRunning()` and the `/state` API endpoint?

The `isRunning()` method is an in-process function available within the Node.js runtime that checks internal flags directly on the `AgentSessionWrapper` instance. The `/state` endpoint is an HTTP interface that encapsulates this logic for external clients, returning a JSON payload after validating the RPC connection via `isAlive()`. Use `isRunning()` for internal logic and the API endpoint for cross-service communication.

### How do I listen for running state changes from a React component?

Import `subscribeRunningSessions` from `@/lib/rpc-manager` to register a callback that receives an array of currently running session IDs. Alternatively, use the `useAgentSession` hook (defined in [`hooks/useAgentSession.ts`](https://github.com/agegr/pi-web/blob/main/hooks/useAgentSession.ts)) which wraps this subscription logic with React state management. For server-sent events directly, connect to `GET /api/agent/running/events`.

### What internal flags determine if `AgentSessionWrapper.isRunning()` returns true?

According to the source code in [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts), the method returns true if any of the following are active: **`promptRunning`**, **`inner.isStreaming`**, **`inner.isCompacting`**, or **`inner.isBashRunning`**. These flags track distinct execution phases including prompt processing, response streaming, memory compaction, and bash command execution.

### Can I check the running status of multiple sessions at once?

Yes. Use `getRegistry()` from [`lib/rpc-manager.ts`](https://github.com/agegr/pi-web/blob/main/lib/rpc-manager.ts) to iterate over all active session wrappers and filter by `isRunning()`. For client-side applications, subscribe to `subscribeRunningSessions()` which broadcasts the complete set of running session IDs whenever any session's status changes, eliminating the need to poll individual endpoints.