How the Sidebar Polls `/api/agent/running` and Pauses in Background Tabs
The sidebar polls GET /api/agent/running every 2.5 seconds while the browser tab remains visible, automatically pausing network requests via the visibilitychange event when users switch tabs to eliminate unnecessary CPU and bandwidth consumption.
The agegr/pi-web repository implements an efficient real-time polling mechanism to keep the sidebar synchronized with active agent sessions. Through the useAgentSession custom hook, the application maintains near-real-time updates while respecting browser resource constraints through intelligent background tab detection as documented in AGENTS.md.
Polling Architecture and Interval Configuration
The polling mechanism centers on a lightweight periodic fetch operation configured to balance responsiveness against network overhead. Inside hooks/useAgentSession.ts, the implementation establishes a setInterval timer set to 2500 milliseconds (2.5 seconds).
Each interval tick executes an asynchronous fetch to /api/agent/running, retrieving a JSON array of currently active session IDs. The hook then reconciles this server state with the local React state, ensuring the sidebar UI reflects the latest running agents without requiring a page refresh.
Background Tab Detection with the Page Visibility API
To prevent wasteful network activity when users are not actively viewing the interface, the implementation leverages the standard Page Visibility API. This browser-native interface provides reliable detection of tab visibility states without relying on blur or focus events that can trigger inconsistently across browsers.
Listening for visibilitychange Events
The useAgentSession hook attaches an event listener to document.addEventListener('visibilitychange', handler) during its initialization phase. Within the handler function, the code inspects the document.hidden property—a boolean that returns true when the tab is backgrounded, minimized, or otherwise obscured from view.
This approach provides deterministic state detection across all modern browsers, distinguishing between true background states and temporary UI interactions that might trigger focus events.
Pausing and Resuming the Interval
The polling state machine implements two distinct transitions based on visibility:
- Pause: When
document.hiddenevaluates totrue, the hook executesclearInterval(timer), immediately halting further network requests and releasing the timer resource. - Resume: When the tab regains visibility (
document.hiddenisfalse), the hook reinitializes the interval viasetInterval, resuming the 2.5-second polling cycle without requiring a full page reload.
The cleanup function within the useEffect hook ensures that both the interval timer and the visibility event listener are properly disposed when the component unmounts, preventing memory leaks in long-running single-page applications.
Implementation in useAgentSession.ts
The following pseudocode illustrates the core polling logic extracted from the hook implementation:
useEffect(() => {
let timer: NodeJS.Timeout | null = null;
const startPolling = () => {
timer = setInterval(async () => {
const running = await fetch('/api/agent/running').then(r => r.json());
setRunningSessions(running);
}, 2500);
};
const stopPolling = () => {
if (timer) clearInterval(timer);
timer = null;
};
// Initialize polling only if tab is currently visible
if (!document.hidden) startPolling();
// Handle tab visibility changes
const onVisibilityChange = () => {
if (document.hidden) stopPolling();
else startPolling();
};
document.addEventListener('visibilitychange', onVisibilityChange);
return () => {
stopPolling();
document.removeEventListener('visibilitychange', onVisibilityChange);
};
}, []);
This pattern ensures that the sidebar maintains session awareness during active use while conserving client and server resources during periods of inactivity.
The /api/agent/running Endpoint
The server-side counterpart resides in app/api/agent/running/route.ts. This route handler returns a lightweight JSON payload containing an array of currently executing session identifiers. The endpoint is optimized for high-frequency polling, minimizing database query overhead and response payload size to support the 2.5-second client-side polling interval efficiently.
According to the source code analysis, this endpoint provides the snapshot data consumed by the useAgentSession hook to reconcile local state against the server truth.
Summary
- The sidebar polls
/api/agent/runningat 2.5-second intervals to maintain real-time session awareness. - Polling automatically pauses when
document.hiddenistruevia the Page Visibility API, conserving network and CPU resources. - The
useAgentSessionhook inhooks/useAgentSession.tsencapsulates both the polling logic and visibility state management. - The
app/api/agent/running/route.tsendpoint provides optimized, lightweight session data for frequent client requests. - Cleanup handlers prevent memory leaks by removing interval timers and event listeners on component unmount.
Frequently Asked Questions
How often does the sidebar poll the running agents endpoint?
The sidebar initiates a fetch request to /api/agent/running every 2.5 seconds (2500 milliseconds) while the browser tab remains visible. This interval is hardcoded in the useAgentSession hook to balance real-time updates against network efficiency.
What happens to the polling when I switch browser tabs?
When you switch to a different tab or minimize the window, the visibilitychange event fires and sets document.hidden to true. The hook immediately clears the polling interval using clearInterval, completely stopping network requests until you return to the tab.
Where is the polling logic implemented in the codebase?
The primary polling logic lives in hooks/useAgentSession.ts, which manages the setInterval timer, visibility change detection, and state reconciliation. The server endpoint that responds to these requests is located at app/api/agent/running/route.ts.
Why does the application pause polling instead of continuing in the background?
Pausing polling prevents unnecessary network traffic and reduces server load when users are not actively viewing the interface. This approach also conserves client-side battery life and CPU cycles, following best practices for background tab behavior in modern web applications as outlined in the repository's AGENTS.md documentation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →