> ## Documentation Index
> Fetch the complete documentation index at: https://docs.instructorphp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Operations

# Symfony Operations Guide

This guide explains how the current Symfony package behaves in the runtime shapes that matter most in production:

* web controllers and page requests
* JSON APIs and streaming endpoints
* Messenger workers
* CLI commands

The package already ships one coherent operational baseline.
What changes by app shape is which optional delivery layer you put on top of that baseline.

## Built-In Baseline

The built-in operational surface is:

* one package-owned runtime bus at `Cognesy\Events\Contracts\CanHandleEvents`
* optional Symfony EventDispatcher mirroring controlled by `instructor.events.dispatch_to_symfony`
* optional projected progress updates at `Cognesy\Instructor\Symfony\Delivery\Progress\Contracts\CanHandleProgressUpdates`
* optional Messenger observation forwarding under `instructor.delivery.messenger`
* optional CLI observation output under `instructor.delivery.cli`
* package-owned telemetry exporter selection, projector composition, and lifecycle cleanup
* package-owned logging presets attached to the same runtime bus

That means:

* logging and telemetry are built in once enabled
* Symfony listener mirroring is optional
* Messenger observation forwarding is optional
* SSE, WebSockets, Mercure, and polling layers are still application-owned

## Web Controllers

Typical shape:

* synchronous request or form handling
* normal Symfony controller lifecycle
* request-scoped route and request metadata available for enrichment

Recommended package setup:

```yaml theme={null}
instructor:
  events:
    dispatch_to_symfony: true

  logging:
    enabled: true
    preset: development

  telemetry:
    enabled: true
    driver: otel
# @doctest id="359c"
```

What is built in:

* the runtime bus remains the source of truth
* Symfony listeners can observe mirrored lifecycle events
* telemetry flushes on kernel terminate
* logging enrichers can use request-aware framework data when available

What stays application-specific:

* controller-specific domain listeners
* UI notifications
* any transport from runtime progress into browser-visible updates

## JSON APIs And Streaming Endpoints

Typical shape:

* HTTP request/response flow
* API monitoring and correlation matter more than controller-local side effects
* partial progress may need to feed SSE, WebSockets, Mercure, or polling

Recommended package setup:

```yaml theme={null}
instructor:
  telemetry:
    enabled: true
    driver: otel

  logging:
    enabled: true
    preset: production

  delivery:
    progress:
      enabled: true
# @doctest id="d88a"
```

What is built in:

* the raw event stream stays on `CanHandleEvents`
* the package projects stable `RuntimeProgressUpdate` objects onto the progress bus
* telemetry and logging stay attached to the internal bus instead of depending on Symfony listeners

What stays application-specific:

* SSE response formatting
* WebSocket or Mercure publication
* API-specific mapping from `RuntimeProgressUpdate` into client-visible payloads

The important rule is:
build transport-specific streaming on top of `RuntimeProgressUpdate`, not on assumptions that every raw runtime event should become a public API payload.

## Messenger Workers

Typical shape:

* queued execution
* background follow-up work
* no active `RequestStack`

Recommended package setup:

```yaml theme={null}
instructor:
  delivery:
    messenger:
      enabled: true
      bus_service: message_bus
      observe_events:
        - Cognesy\Agents\Events\AgentExecutionCompleted
        - Cognesy\AgentCtrl\Event\AgentExecutionCompleted

  telemetry:
    enabled: true
    driver: otel

  logging:
    enabled: true
    preset: production
# @doctest id="f585"
```

What is built in:

* `ExecuteAgentCtrlPromptMessage` for queued AgentCtrl execution
* `ExecuteNativeAgentPromptMessage` for queued native-agent execution and optional session resume
* `RuntimeObservationMessage` for explicit observation forwarding
* telemetry flush and shutdown hooks around handled, failed, and stopped worker lifecycle events

What stays application-specific:

* which runtime events should be forwarded onto Messenger
* worker-specific retry, dead-letter, or alerting policy
* downstream consumers of forwarded observation messages

Keep Messenger observation explicit.
Use `observe_events` as an allow-list instead of treating Messenger as a generic mirror for the entire raw runtime stream.

## CLI Commands

Typical shape:

* console command or long-running CLI workflow
* no HTTP request context
* human-readable live observation can be useful

Recommended package setup:

```yaml theme={null}
instructor:
  delivery:
    cli:
      enabled: true
      use_colors: true
      show_timestamps: true

  telemetry:
    enabled: true
    driver: otel

  logging:
    enabled: true
    preset: development
# @doctest id="cb0a"
```

What is built in:

* the same runtime bus semantics as HTTP and Messenger flows
* projected progress updates formatted by `SymfonyCliObservationPrinter`
* telemetry flush and shutdown around console terminate and error events

What stays application-specific:

* command-specific output structure
* custom progress formatting beyond the built-in printer
* command orchestration and retries

CLI output is opt-in for a reason:
the package keeps runtime correctness on the internal bus and treats terminal formatting as a view over projected progress, not as a second event model.

## Built-In Versus Optional

Built in once enabled by config:

* logging presets
* telemetry exporter selection
* telemetry lifecycle cleanup
* progress projection
* Messenger execution handlers
* Messenger observation bridge
* CLI progress printer

Still application-owned:

* browser delivery transports
* SSE and WebSocket response format
* Mercure integration
* alert routing and incident handling
* domain-specific listeners and notifications

## Operational Rule Of Thumb

Use the package-owned runtime bus for correctness and observability.
Use the projected progress bus for transport-specific UX.
Use Symfony listeners and Messenger forwarding only where they improve application integration, not as the primary source of runtime truth.
