Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ LANGFUSE_TRACE_METADATA=ticket_key,ticket_type,project_id,workflow_step,repo,pr_
# joins the Langfuse compose network.
# - The ClickHouse service is then reachable as clickhouse:9000.
GRAFANA_PORT=3010
GRAFANA_BASE_URL=http://localhost:3010
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=grafana
LANGFUSE_DOCKER_NETWORK=langfuse_default
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,10 @@ Forge agents can access external tools via MCP (Model Context Protocol):

Configure in `mcp-servers.json`. By default, MCP tools are read-only.

Forge also provides a separate read-only session-inspection API and optional MCP
server for users who want to inspect workflow progress without Redis, Langfuse,
or Grafana credentials. See [Session Inspection](docs/reference/session-inspection.md).

## Project Structure

```
Expand Down
1 change: 1 addition & 0 deletions docs/developer-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ LANGFUSE_TRACE_METADATA=ticket_key,ticket_type,project_id,workflow_step,repo,pr_

# Grafana dashboard stack
GRAFANA_PORT=3010
GRAFANA_BASE_URL=http://localhost:3010
LANGFUSE_DOCKER_NETWORK=langfuse_default
CLICKHOUSE_HOST=clickhouse
CLICKHOUSE_PORT=9000
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ graph TD
- [Feature Workflow](guide/feature-workflow.md) — How features flow through Forge
- [Developer Guide](developer-guide.md) — Full local development reference
- [Skills System](skills/index.md) — Customize Forge for your stack
- [Session Inspection](reference/session-inspection.md) — Check workflow progress safely
- [Contributing](dev/contributing.md) — How to contribute

## Key Features
Expand Down
142 changes: 142 additions & 0 deletions docs/reference/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,148 @@ Exposes Prometheus-format metrics for the API server.

Worker metrics are available separately at `http://localhost:8001/metrics`.

---

### Session Summary

```http
GET /api/v1/sessions/{ticket_key}/summary
```

Returns a safe, read-only summary of a Forge workflow session for a Jira ticket.
This endpoint is intended for users who want to inspect session progress without
direct Redis, Langfuse, or Grafana access.

The response is curated and intentionally excludes raw prompts, model messages,
generated artifacts, tool inputs, and full trace metadata.

**Query parameters:**

| Parameter | Default | Description |
|-----------|---------|-------------|
| `logs_limit` | `0` | Optional number of Redis log entries to include. Allowed range: `0` to `50`. Keep this at `0` for the safest user-facing summary. |

**Example:**

```bash
curl http://localhost:8000/api/v1/sessions/AISOS-123/summary
```

**Response:**

```json
{
"summary": {
"ticket_key": "AISOS-123",
"found": true,
"current_node": "implement_task",
"status": "running",
"is_paused": false,
"is_blocked": false,
"retry_count": 0,
"last_error": null,
"ticket_type": "Feature",
"repository": "org/repo",
"pr_number": 42,
"pr_url": "https://github.com/org/repo/pull/42",
"ci_status": "pending",
"artifacts_present": {
"prd": true,
"spec": true,
"rca": false,
"plan": true,
"epics": true,
"tasks": true,
"qa_history": false
},
"observability_links": {
"grafana_issue_detail": "http://localhost:3010/d/forge-issue-detail/forge-issue-detail?orgId=1&var-jira_issue=AISOS-123"
},
"raw_state_exposed": false
},
"notes": [
"This summary is read-only and excludes raw prompts, model messages, generated artifacts, and tool inputs."
]
}
```

Returns `404` if Forge has no persisted session state for the ticket.

---

### Ticket Observability

```http
GET /api/v1/observability/tickets/{ticket_key}
```

Returns safe Langfuse API aggregates for one Jira ticket: total cost,
tokens, latency, workflow-step breakdown, and recent observation metadata.

The endpoint uses Langfuse API reads only and does not expose raw prompts, model
messages, model outputs, tool inputs, or raw trace payloads.

**Query parameters:**

| Parameter | Default | Description |
|-----------|---------|-------------|
| `hours` | `720` | Lookback window, from 1 hour to 90 days |
| `limit` | `50` | Maximum rows for step and observation lists |

### Ticket Traces

```http
GET /api/v1/observability/tickets/{ticket_key}/traces
```

Returns Langfuse traces for one Jira ticket session. By default `full=true`, so
the response includes full trace details from Langfuse, including raw
input/output fields when Langfuse provides them.

**Query parameters:**

| Parameter | Default | Description |
|-----------|---------|-------------|
| `hours` | `720` | Lookback window, from 1 hour to 90 days |
| `limit` | `10` | Maximum number of traces to return |
| `full` | `true` | Hydrate each trace through the Langfuse trace detail API |

### Trace Detail

```http
GET /api/v1/observability/traces/{trace_id}
```

Returns one full Langfuse trace by trace id, including raw input/output fields
when Langfuse provides them.

### Model Usage

```http
GET /api/v1/observability/model-usage
```

Returns aggregate model calls, cost, tokens, and average latency.

### Workflow Funnel

```http
GET /api/v1/observability/workflow-funnel
```

Returns workflow-step issue count, trace count, observation count, cost, and
latency aggregates.

### Observability Health

```http
GET /api/v1/observability/health
```

Returns metadata coverage checks for the fields required by Forge dashboards,
including missing `project_id`, `ticket_type`, `workflow_step`, and `session_id`
counts.

## Webhook Configuration

### Jira
Expand Down
10 changes: 8 additions & 2 deletions docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,11 @@ These variables are used by `docker-compose.yml`, `devtools/docker-compose.dev.y
| Variable | Description |
|----------|-------------|
| `GRAFANA_PORT` | Host port for Grafana (default: `3010`) |
| `GRAFANA_BASE_URL` | Public/base URL for Grafana, used by Forge session summaries and MCP responses to include dashboard links |
| `GRAFANA_ADMIN_USER` | Grafana admin user (default: `admin`) |
| `GRAFANA_ADMIN_PASSWORD` | Grafana admin password (default: `grafana`) |
| `LANGFUSE_DOCKER_NETWORK` | External Docker/Podman network for self-hosted Langfuse when using `devtools/grafana/compose.langfuse-network.yml` (default: `langfuse_default`) |
| `CLICKHOUSE_HOST` | Langfuse ClickHouse host reachable from the Grafana container |
| `CLICKHOUSE_HOST` | Langfuse ClickHouse host reachable from Grafana |
| `CLICKHOUSE_PORT` | Langfuse ClickHouse native protocol port (default: `9000`) |
| `CLICKHOUSE_DATABASE` | Langfuse ClickHouse database (default: `default`) |
| `CLICKHOUSE_USER` | Langfuse ClickHouse user |
Expand All @@ -127,4 +128,9 @@ These variables are used by `docker-compose.yml`, `devtools/docker-compose.dev.y

### MCP Servers

MCP server configuration lives in `mcp-servers.json`, not `.env`. See the [MCP servers section](https://github.com/forge-sdlc/forge/blob/main/mcp-servers.json) of the repository.
MCP server configuration for Forge agents lives in `mcp-servers.json`, not `.env`.
The checked-in file is loaded by Forge agents and should only include external
tooling those agents need.

The user-facing Forge session MCP server is configured separately in the user's
assistant client. See [Session Inspection](session-inspection.md).
100 changes: 100 additions & 0 deletions docs/reference/session-inspection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Session Inspection

Forge exposes a session and observability inspection surface so users can
understand what is happening in their workflow without needing Redis, Langfuse,
or Grafana credentials.

The session summary and aggregate observability tools are deliberately curated.
They do not expose raw prompts, model messages, generated artifacts, tool inputs,
or full trace metadata. Full trace tools are also available when users need the
underlying Langfuse trace data.

## HTTP API

Use the Forge API when you want a direct integration or a quick command-line
check:

```bash
curl http://localhost:8000/api/v1/sessions/AISOS-123/summary
```

The session endpoint returns workflow progress, current status, PR information,
CI status, artifact presence, and observability links when configured.

The observability endpoints read through the Langfuse API:

| Endpoint | Purpose |
|----------|---------|
| `/api/v1/observability/tickets/{ticket_key}` | Ticket cost, tokens, latency, workflow steps, and recent observation metadata |
| `/api/v1/observability/tickets/{ticket_key}/traces` | Full Langfuse traces for a ticket session |
| `/api/v1/observability/traces/{trace_id}` | One full Langfuse trace by id |
| `/api/v1/observability/model-usage` | Aggregate model calls, cost, tokens, and latency |
| `/api/v1/observability/workflow-funnel` | Workflow-step issue, trace, cost, and latency aggregates |
| `/api/v1/observability/health` | Metadata coverage checks for dashboard-required labels |

See the [API reference](api.md#session-summary) for the full response shape.

## Optional Claude MCP Setup

Forge also ships a read-only stdio MCP server named `forge-session-mcp`. This is
for user assistants such as Claude Desktop or Claude Code. It should be added to
the user's assistant configuration, not to Forge's `mcp-servers.json`.

Do not add `forge-session-mcp` to the checked-in `mcp-servers.json`: that file is
loaded by Forge agents themselves, and the session-inspection server is meant for
external user inspection.

### Claude Code

From the Forge repository:

```bash
uv sync
claude mcp add-json "forge-session" \
'{"type":"stdio","command":"uv","args":["run","forge-session-mcp"],"cwd":"'"$(pwd)"'"}'
```

Then ask Claude for a session summary by Jira ticket key, for example:

```text
Show me the Forge session summary for AISOS-123.
```

### Manual MCP JSON

If your MCP client accepts JSON configuration, add this server entry and adjust
`cwd` to the local Forge repository path:

```json
{
"forge-session": {
"type": "stdio",
"command": "uv",
"args": ["run", "forge-session-mcp"],
"cwd": "/path/to/forge"
}
}
```

The server reads the same `.env` configuration as Forge, so it must be run from a
working Forge checkout with access to the configured Redis/checkpoint backend and
Langfuse API credentials.

## Available MCP Capability

The MCP server provides:

| Capability | Description |
|------------|-------------|
| `get_session_summary` | Tool that returns a safe summary for a Jira ticket key |
| `get_ticket_observability` | Tool that returns safe cost/token/latency aggregates for one ticket |
| `get_session_traces` | Tool that returns Langfuse traces for one Jira ticket session; full trace data by default |
| `get_trace` | Tool that returns one full Langfuse trace by trace id |
| `get_model_usage` | Tool that returns aggregate model calls, cost, tokens, and latency |
| `get_workflow_funnel` | Tool that returns workflow-step issue, trace, cost, and latency aggregates |
| `get_observability_health` | Tool that returns metadata coverage checks for dashboard-required fields |
| `forge://sessions/{ticket_key}` | Resource URI that returns the same summary as JSON |

The MCP responses include `raw_state_exposed: false` or
`raw_trace_data_exposed: false` for curated responses. Full trace responses use
`full_trace_data_exposed: true`.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ dev = [
[project.scripts]
forge = "forge.cli:main"
forge-serve = "forge.main:main"
forge-session-mcp = "forge.mcp.session:main"

[tool.hatch.build.targets.wheel]
packages = ["src/forge"]
Expand Down
4 changes: 4 additions & 0 deletions src/forge/api/routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
from forge.api.routes.health import router as health_router
from forge.api.routes.jira import router as jira_router
from forge.api.routes.metrics import router as metrics_router
from forge.api.routes.observability import router as observability_router
from forge.api.routes.sessions import router as sessions_router

__all__ = [
"github_router",
"health_router",
"jira_router",
"metrics_router",
"observability_router",
"sessions_router",
]
Loading
Loading