diff --git a/README.md b/README.md index 6248ace..8f94f3e 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,14 @@ OpenTelemetry-first. Vendor-neutral. Never an agent-code change.** [![CI](https://img.shields.io/badge/CI-ruff_·_mypy--strict_·_pytest_≥90%25-brightgreen.svg)](./.github/workflows/ci.yml)

- ForgeSight demo — instrument an agent and see the trace, cost, and a verified tamper-evident audit trail + ForgeSight quick start — pip install, instrument any agent in a few lines, run, and see the captured trace + cost

-> ⬆️ Real output, no edits — `uv run python examples/demo.py` ([source](./examples/demo.py)). -> Offline here; the same telemetry ships to any backend by changing one config line. +> ⬆️ **`pip install` → instrument any agent (just wrap it) → run.** Real output, no edits +> ([examples/quickstart.py](./examples/quickstart.py)). The same code ships to any backend by +> changing one config line. The offline [examples/demo.py](./examples/demo.py) also shows the +> tamper-evident audit trail. ```python import forgesight diff --git a/docs/assets/demo.gif b/docs/assets/demo.gif index adee868..2c7ce87 100644 Binary files a/docs/assets/demo.gif and b/docs/assets/demo.gif differ diff --git a/docs/assets/demo.tape b/docs/assets/demo.tape index 1d128b5..9b788a9 100644 --- a/docs/assets/demo.tape +++ b/docs/assets/demo.tape @@ -1,23 +1,45 @@ -# ForgeSight README demo. Regenerate with: vhs docs/assets/demo.tape +# ForgeSight README demo — install → instrument → run. Regenerate: vhs docs/assets/demo.tape +# (requires the prepared venv at /tmp/fs-gif; see the prep steps in the PR.) Output docs/assets/demo.gif -Require uv - Set Shell zsh Set FontSize 20 -Set Width 1280 -Set Height 540 +Set Width 1320 +Set Height 640 Set Padding 22 Set Theme "Dracula" -Set TypingSpeed 55ms +Set TypingSpeed 45ms Hide -Type "uv sync --all-packages >/dev/null 2>&1; clear" +Type "cd /tmp/fs-gif && export VIRTUAL_ENV_DISABLE_PROMPT=1 PIP_DISABLE_PIP_VERSION_CHECK=1 && source venv/bin/activate && export PROMPT='$ ' && clear" Enter -Sleep 2s +Sleep 1500ms Show -Type "uv run python examples/demo.py" -Sleep 600ms +# 1) install +Type "pip install -q 'forgesight[otel]'" +Sleep 400ms +Enter +Sleep 2500ms +Type "pip list | grep forgesight" +Sleep 400ms +Enter +Sleep 3000ms +Type "clear" +Enter +Sleep 300ms + +# 2) instrument any agent — wrap it, that's it +Type "cat quickstart.py" +Sleep 400ms +Enter +Sleep 5500ms +Type "clear" +Enter +Sleep 300ms + +# 3) run it +Type "python quickstart.py" +Sleep 400ms Enter -Sleep 5s +Sleep 4500ms diff --git a/examples/quickstart.py b/examples/quickstart.py new file mode 100644 index 0000000..cfd2b7f --- /dev/null +++ b/examples/quickstart.py @@ -0,0 +1,21 @@ +"""Quick start — instrument any agent with ForgeSight. Run: python quickstart.py""" + +import forgesight +from forgesight import telemetry +from forgesight_core import InMemoryExporter, MetricConfig, get_runtime + +sink = InMemoryExporter() # swap exporters for ["otel"], ["datadog"], ["langfuse"] — no code change +forgesight.configure(exporters=[sink], sync_export=True, metrics=MetricConfig(enabled=False)) + +with telemetry.agent_run("pr-reviewer", metadata={"team": "platform"}) as run: # wrap your agent + with run.llm_call("anthropic", "claude-sonnet-4-5") as call: + call.record_usage(input=1240, output=340) # tokens → cost, derived for you + call.set_cost(0.0123) + with run.tool_call("github_get_diff"): + ... + +get_runtime().force_flush() +for r in sorted(sink.records, key=lambda x: x.start_unix_nanos): + cost = f" ${r.llm.cost_usd:.4f}" if r.llm and r.llm.cost_usd else "" + print(f" captured: {r.kind.value:<6} {r.name}{cost}") +print("\n -> same code ships to Jaeger / Datadog / Langfuse / Prometheus - one config line.")