# How Agents View Detects Session Termination Status: Parsing Logic Explained

> Understand how Agents View detects session termination by parsing the final task-lifecycle event in agent JSONL logs, not external signals. Learn the logic.

- Repository: [Kenn Software/agentsview](https://github.com/kenn-io/agentsview)
- Tags: deep-dive
- Published: 2026-07-04

---

**Agents View derives session termination status by analyzing the final task-lifecycle event in an agent's JSONL log file, not from external system signals.**

The open-source project `kenn-io/agentsview` implements a sophisticated **detection method for session termination status** that inspects agent-specific log files at parse time. Instead of relying on explicit shutdown signals or process exit codes, the system reads the last recorded event to determine whether a session ended cleanly, is awaiting user input, or was interrupted mid-task.

## How Termination Status Is Derived

During the parsing phase, each agent-specific parser scans the entire JSONL file to identify the most recent task-related event. This **event-driven detection** ensures the status reflects the actual final state of the agent when the log was written.

### Codex Parser Implementation

In [`internal/parser/codex.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/codex.go), the parser tracks the most recent task event using the `lastTaskEvent` field within the `codexSessionBuilder` struct. As the parser processes each line, it updates this field whenever it encounters task lifecycle events like `task_started` or `task_complete`.

After scanning the complete file, the parser calls `classifyCodexTermination(b.lastTaskEvent)` to map the final event to a normalized status:

- **`task_complete`** → `"awaiting_user"` (agent finished and is waiting for user input)
- **`task_started`** without subsequent `task_complete` → `"working"` (agent was still active when file closed)
- **No task events** → `"clean"` (normal session termination without special lifecycle markers)

The relevant logic appears around lines 77-81 where `lastTaskEvent` is documented, with the classification call at line 1388.

```go
// Inside internal/parser/codex.go after scanning completes
sess := &ParsedSession{
    // ... other fields ...
    TerminationStatus: classifyCodexTermination(b.lastTaskEvent),
}

```

### Claude Parser Implementation

The Claude parser follows a similar pattern in [`internal/parser/claude.go`](https://github.com/kenn-io/agentsview/blob/main/internal/parser/claude.go), extracting the `termination` attribute from Claude's JSON output. The parser converts raw termination strings into the normalized `TerminationStatus` enum through a classification function.

```go
func classifyClaudeTermination(raw string) TerminationStatus {
    switch raw {
    case "clean":
        return TerminationClean
    case "awaiting_user":
        return TerminationAwaitingUser
    // ... other mappings ...
    default:
        return TerminationUnknown
    }
}

```

## Database Storage and API Filtering

Once derived, the termination status persists to the database and becomes queryable through the REST API.

### Schema Definition

The `termination_status` column is defined in [`internal/postgres/schema.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/schema.go) at line 82 as a `TEXT` field with a dedicated index for efficient filtering:

```sql
CREATE TABLE sessions (
    -- ... other columns ...
    termination_status TEXT,
    -- ...
);
CREATE INDEX idx_sessions_termination_status ON sessions(termination_status);

```

### API Query Parameters

The API exposes this field through query parameters defined in [`internal/server/huma_routes_sessions.go`](https://github.com/kenn-io/agentsview/blob/main/internal/server/huma_routes_sessions.go). Clients can filter sessions using values like `?termination=clean` or `?termination=active`.

```go
type SessionListFilters struct {
    Termination string `query:"termination" doc:"Filter by termination reason"`
}

```

## Incremental Agent Handling

For agents operating in incremental mode, the **detection method for session termination status** operates differently. Rather than re-deriving the status on every partial update, the `parsediff` component treats the stored value as informational only.

In [`internal/sync/parsediff_report.go`](https://github.com/kenn-io/agentsview/blob/main/internal/sync/parsediff_report.go), the constant `FieldTerminationStatus = "termination_status"` at line 121 ensures that termination status changes between incremental updates do not trigger false positive diffs. This prevents spurious synchronization cycles when only the termination state has shifted during active processing.

## Summary

- **Event-driven parsing**: Agents View determines termination status by inspecting the last task event in JSONL logs, not external signals.
- **Codex implementation**: Uses `lastTaskEvent` tracking and `classifyCodexTermination()` to map final states to `"awaiting_user"`, `"working"`, or `"clean"`.
- **Claude implementation**: Extracts and normalizes the `termination` field from Claude's JSON output.
- **Database persistence**: Stores status in the `termination_status` column with proper indexing in [`internal/postgres/schema.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/schema.go).
- **Incremental handling**: The `parsediff` component mirrors existing values to avoid unnecessary updates during incremental processing.

## Frequently Asked Questions

### How does Agents View detect if a Codex session ended cleanly?

Agents View scans the entire Codex JSONL log to find the last task event. If the final event is `task_complete`, the status becomes `"awaiting_user"`. If `task_started` appears without a matching completion event, the status is `"working"`. When no task events exist, the session is marked as `"clean"`.

### Where is the termination status stored in the database?

The status is stored in the `termination_status` column of the `sessions` table, defined in [`internal/postgres/schema.go`](https://github.com/kenn-io/agentsview/blob/main/internal/postgres/schema.go). The schema includes an index `idx_sessions_termination_status` to optimize query performance when filtering by termination state.

### Can I filter sessions by termination status via the API?

Yes. The API supports filtering through the `termination` query parameter, as implemented in [`internal/server/huma_routes_sessions.go`](https://github.com/kenn-io/agentsview/blob/main/internal/server/huma_routes_sessions.go). You can pass values like `?termination=clean` or `?termination=awaiting_user` to retrieve specific session subsets.

### Why doesn't the termination status change during incremental updates?

For incremental agents, the termination status is treated as informational only to prevent spurious diffs. The `parsediff` component in [`internal/sync/parsediff_report.go`](https://github.com/kenn-io/agentsview/blob/main/internal/sync/parsediff_report.go) maintains the existing `termination_status` value rather than re-deriving it on every partial file update, ensuring stable synchronization.