{% comment %} Shared Agents detail content. Included by detail.html, which extends the SDK adapter (scitex_sdk/app/app_shell.html) and fills scitex_app_content. `url_base` is the app mount prefix so the back link and the lifecycle form action are correct at any mount. {% endcomment %}
{# Fragment render (?partial=1 into the fleet Details pane): no app #} {# header - the fleet page already owns the one header row. The full #} {# detail.html page includes the header through its own block. #} {% if not fragment %} {% include "scitex_agent_container/_app_header.html" %} {% endif %} {% if not agent %} {% else %} {% comment %} Last delivery outcome: lifecycle/message POSTs redirect back here with ?operation=&state=&message=, and this banner is where that delivery status lands — next to the forms that caused it. Only server-minted operation names render (see _delivery_notice), so the query string cannot inject banner copy. {% endcomment %} {% if notice %}
{{ notice.operation }}: {{ notice.state }} {% if notice.message %}{{ notice.message }}{% endif %} {% if notice.dispatch_id %}dispatch {{ notice.dispatch_id }}{% endif %}
{% endif %} {% if not fragment %}

{{ agent.name }}

{% endif %} {# Operator 2026-10-22: 5 tabs (Identity, Runtime Activity, Control, #} {# Resources, Recent Session Log) — the standalone Message thread card is #} {# gone (its thread renders in the center DM pane). No-JS fallback: every #} {# panel is visible until fleet-details.js activates the first tab. POST #} {# forms/endpoints inside are byte-identical to the old
cards. #}
{{ agent.state_label }} {% if cross_host %}cross-host{% endif %}
Runtime
{{ agent.runtime }}
Billing
{{ agent.billing_mode }}
Auth identity
{{ agent.auth_identity }}
Identity source
{{ agent.runtime_identity_source }}
Harness
{{ agent.harness }}
Role
{{ agent.role }}
Engine
{{ agent.engine }}
Model
{{ agent.model }}
Project
{{ agent.project }}
Host
{{ agent.host }}
PID
{{ agent.pid|default:"—" }}
a2a port
{{ agent.a2a_port|default:"—" }}
Turn URL
{{ agent.turn_url|default:"—" }}
Session
{{ agent.session|default:"—" }}
{% if agent.detail.started_at %}
Started
{{ agent.detail.started_at }}
{% endif %}
Phase
{% if agent.activity.phase.state == "observed" %}{{ agent.activity.phase.value }}{% else %}Unknown{% endif %}
Operation
{% if agent.activity.operation.state == "observed" %}{{ agent.activity.operation.value }}{% else %}Unknown{% endif %}
Turn elapsed
{% if agent.activity.turn_elapsed.state == "observed" %}{{ agent.activity.turn_elapsed.value }} s{% else %}Unknown{% endif %}
Last progress
{% if agent.activity.last_progress.state == "observed" %}{{ agent.activity.last_progress.value }}{% else %}Unknown{% endif %}
Queue
{% if agent.activity.queue.state == "observed" %}{{ agent.activity.queue.value }}{% else %}Unknown{% endif %}
Inference
{% if agent.activity.inference.state == "observed" %}{{ agent.activity.inference.value }}{% else %}Unknown{% endif %}
Tool
{% if agent.activity.tool.state == "observed" %}{{ agent.activity.tool.value }}{% else %}Unknown{% endif %}
Wait
{% if agent.activity.wait.state == "observed" %}{{ agent.activity.wait.value }}{% else %}Unknown{% endif %}

Only runner-published state is shown. Unknown means SAC has no authoritative signal; session logs are not guessed into activity.

{% if agent.state_detail %}

Status: {{ agent.state_detail }}

{% endif %} {% if agent.detail_error %}

Status endpoint unavailable: {{ agent.detail_error }}

{% endif %} {% if can_operate %}

{% if cross_host %} Cross-host control — this action is recorded in the operator audit trail. {% else %} You are an authorized lifecycle operator for this node's agents. {% endif %}

{% if csrf_token %}{% endif %}
{% comment %} Message / steer and the three SAC UI-control keys. Both POST to the agent's OWN bridge endpoint (its published turn_url) — the GUI never constructs a host/port and never drives tmux. Each submit carries a dispatch id so a double-click cannot inject the text twice. {% endcomment %} {# Message thread (operator 2026-10-23): chat-style, Cards DM idiom #} {# ported leaf-side (no cross-app dependency, different ports). Same #} {# POST endpoint + gate; operator sends render right, session lines #} {# render left. The console still keeps no operator transcript — the #} {# last-send banner below is the delivery receipt. #}

Messages

{% if notice and notice.operation == "message" or notice and notice.operation == "control" %}
{{ notice.message|default:notice.operation }}
{{ notice.operation }} · {{ notice.state }}
{% endif %} {% if agent.session_lines %} {% for line in agent.session_lines|slice:"-8:" %}
{{ line }}
{% endfor %} {% elif not notice %}

No messages yet. Send the first one below.

{% endif %}
{% if csrf_token %}{% endif %}

UI control

Positional input to the agent's live terminal — Enter submits, Escape dismisses, C-c interrupts. Nothing else is available.

{% if csrf_token %}{% endif %}
{% for key in control_keys %} {% endfor %}
{% else %}

Read-only. Control requires an identity listed in the lifecycle-operator allowlist{% if cross_host %} — or, for cross-host agents, the cross-host operator allowlist{% endif %}.

{% endif %}
{# Message thread card removed (operator 2026-10-22): its thread already #} {# renders in the fleet center DM pane (moved out of Control above). #}
{% with r=agent.resources %} {% if r.state == "ok" %}
PID
{{ r.pid }}
RSS
{{ r.rss|default:"—" }}
VSZ
{{ r.vsz|default:"—" }}
CPU ticks
{{ r.cpu_ticks|default:"—" }}
Process tree
{{ r.tree_size }} process(es)
{% elif r.state == "namespace" %}

PID {{ r.pid }} is reported by the listener but runs in a separate pid namespace (apptainer isolation) — live CPU/memory cannot be read from the web process, so no value is shown rather than a guessed one.

{% else %}

No process to read (agent not started or stopped).

{% endif %} {% endwith %}
{% if agent.session_error %}

Log unavailable: {{ agent.session_error }}

{% elif agent.session_lines %}
    {% for line in agent.session_lines %}
  • {{ line }}
  • {% endfor %}

Tail (last {{ agent.session_lines|length }} lines), secrets redacted.

{% else %}

No session log recorded yet.

{% endif %}
{% endif %}