# AbstractFramework - llms-full
> Full text of key files from this repo. Sections are separated by `--- <path> ---`.

--- README.md ---
# AbstractFramework

**Write once. Generate everything.**

A modular, open-source ecosystem for building **durable, observable, multimodal** AI systems. Text, voice, image, video, music — one unified interface, any provider, any model, local or cloud.

AbstractFramework is an ecosystem of composable packages for building AI systems that work in operational reality:

- **Durable by default**: workflows **pause and resume** safely (survive crashes and restarts)
- **Observable**: an append-only **ledger** so any UI can reconstruct state by replaying history
- **Controlled actions**: explicit boundaries for **tool execution**, approvals, and evidence
- **Multimodal**: capability plugins (voice, vision, music) that stay out of your way until you need them

Think of it as an **agentic OS**: durable runs + replay-first observability + multimodal capabilities — write once, run across providers and deployment modes.

> **Prerequisites**: Python 3.10+. Node.js 18+ for browser UIs. An LLM backend (Ollama, LM Studio, vLLM, or a cloud API key).

---

## Two entrypoints

Start lightweight with just the LLM library, or go all-in with a production gateway. Both paths lead to the same ecosystem.

### 1) AbstractCore — LLM SDK + OpenAI-compatible `/v1` server

Start here if you need a lightweight LLM library for scripts, notebooks, or existing applications. No infrastructure required — just `pip install` and call. Add multimodal capabilities with plugins as you grow.

- 9+ providers with identical API (local + cloud)
- Universal tool calling, structured output, streaming
- Media handling (images, PDFs, audio, video)
- OpenAI-compatible HTTP server mode (`/v1`)
- Multimodal via capability plugins (Voice, Vision, Music)

```bash
pip install abstractcore
```

```python
from abstractcore import create_llm

llm = create_llm("ollama", model="qwen3:4b-instruct")
resp = llm.generate("Explain durable execution in 3 bullets.")
print(resp.content)
```

AbstractCore gives you one interface for provider switching, tools, structured output, and media — as a Python SDK or via `/v1` for any OpenAI-compatible client.

### 2) AbstractGateway — durable run control plane (HTTP/SSE APIs)

Start here if you're building persistent AI applications — agents that run for hours, workflows that survive crashes, scheduled tasks. The gateway is your AI control plane: durable runs with ledger replay/streaming and thin clients that can attach/detach across devices.

- Durable execution that survives crashes and restarts
- Append-only ledger (replay-first) for auditability
- Scheduled workflows (cron-style, recurring)
- Multi-client: terminal, browser, tray, Telegram, email
- Start on one device, continue on another

```bash
pip install abstractgateway

export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
export ABSTRACTGATEWAY_WORKFLOW_SOURCE=bundle
export ABSTRACTGATEWAY_FLOWS_DIR="$PWD/bundles"
export ABSTRACTGATEWAY_DATA_DIR="$PWD/runtime/gateway"

abstractgateway serve --host 127.0.0.1 --port 8080
```

Monitor runs from a browser:

```bash
npx @abstractframework/observer   # open http://localhost:3001
```

---

## Author once, run everywhere (AbstractFlow)

AbstractFlow lets you author complex agentic orchestration as portable `.flow` bundles:

1. Open the Flow Editor (`npx @abstractframework/flow`)
2. Build a workflow: LLM steps, tool steps, branching, loops, subflows
3. Export a `.flow` bundle and copy it to `ABSTRACTGATEWAY_FLOWS_DIR`
4. Run it from any gateway-backed client (Observer, AbstractAssistant, Code Web UI, your app)

**AbstractAgent** provides ready-made agent patterns (ReAct, CodeAct, MemAct) that can be used inside flows or standalone.

---

## Monitor and schedule with AbstractObserver

- **Observe**: replay the full ledger of any run, or watch one live over SSE
- **Control**: cancel, resume, or inspect runs from the browser
- **Schedule**: durable schedules (cron-style) owned by the gateway — they survive restarts

---

## Example apps

| App | What it does | Install |
|---|---|---|
| **AbstractCode** | Terminal agentic dev client — durable sessions, tool approvals, `/workflow` support | `pip install abstractcode` |
| **AbstractAssistant** | macOS tray client — gateway-first, workflow picker per session, voice support | `pip install abstractassistant` |
| **AbstractObserver** | Browser UI — monitor, control, and schedule gateway runs | `npx @abstractframework/observer` |
| **Code Web UI** | Browser coding assistant (gateway-backed) | `npx @abstractframework/code` |

---

## Install the pinned ecosystem profile

### Light / Apple / GPU profiles

Choose how the framework runs based on your hardware and constraints. All profiles keep the same interfaces; they mainly change which **local inference stacks** are available.

**Light (default)** — endpoint-only inference (cloud APIs or local OpenAI-compatible servers), no in-process ML engine stacks:

```bash
pip install abstractframework
```

**Apple** — native Apple Silicon local stacks (MLX/Metal) in addition to endpoint providers:

```bash
pip install "abstractframework[apple]"
```

**GPU** — native GPU local stacks (CUDA/ROCm) in addition to endpoint providers:

```bash
pip install "abstractframework[gpu]"
```

---

## Documentation

| Page | What it covers |
|---|---|
| [docs/README.md](docs/README.md) | Documentation hub — pick your starting point |
| [docs/getting-started.md](docs/getting-started.md) | Two entry points + first end-to-end run |
| [docs/architecture.md](docs/architecture.md) | Layered model, durable execution primitives, comparisons |
| [docs/configuration.md](docs/configuration.md) | Minimal config, where defaults live, Core vs Gateway |
| [docs/glossary.md](docs/glossary.md) | Shared terminology (run, ledger, effect, wait, bundle, …) |
| [docs/faq.md](docs/faq.md) | Common questions, comparisons, troubleshooting |
| [docs/api.md](docs/api.md) | Meta-package API (pins, helpers, re-exports) |

---

## Developer setup (from source)

Clone all sibling repos and build everything in editable mode:

```bash
./scripts/clone.sh           # clone 14 repos as siblings
source ./scripts/build.sh    # editable installs into .venv (use `source` to stay in the venv)
```

Then configure:

```bash
abstractcore --config
abstractcore --install
```

---

## License

MIT. See [LICENSE](LICENSE).

--- llms.txt ---
# AbstractFramework
> Meta-package + documentation hub for the AbstractFramework ecosystem (durable, observable agents/workflows).

This repo pins ecosystem package versions and provides a tiny helper API in `abstractframework/`.
Most runtime behavior lives in the individual package repos (AbstractCore/Runtime/Agent/Flow/Gateway/Code).

Quick commands:
- Install pinned stack: `pip install abstractframework`
- Show detected component versions: `python -c "from abstractframework import print_status; print_status()"`

Notes for LLMs working in this repo:
- Prefer `docs/` as the ecosystem-level source of truth.
- Keep changes minimal and ecosystem-level (docs + version pins).
- If you need to change runtime behavior, you likely want the relevant package repo instead of this meta repo.
- Gateway-first hosted browser setups use Gateway user auth, opaque browser
  sessions, and `/console` for account/admin/defaults management. AbstractFlow,
  AbstractCode Web, and AbstractObserver exchange user tokens for app-scoped
  browser sessions and do not persist bearer tokens in browser settings.
  Gateway login responses do not expose session ids/CSRF tokens in JSON, and
  default resolution is Core defaults -> Gateway baseline -> per-user overlay.
  Do not treat the bootstrap `ABSTRACTGATEWAY_AUTH_TOKEN` as a browser-user
  login token. Gateway session cookies are HTTP-only for the session id, use a
  separate CSRF cookie, set `Secure` only under HTTPS, expire, logout cleanly,
  and are revoked when the backing user is disabled/deleted/token-rotated.
- Gateway user isolation is enforced through per-principal runtime routing plus
  a central route-family policy. Ordinary users can use their own runs, ledgers,
  artifacts, KG/session memory, private workflows, session artifacts,
  prompt-cache session names, and defaults overlays. Admin-only workspace
  helpers/import/export and provider prompt-cache controls are advertised as
  unavailable in discovery with machine-readable `admin_required` metadata.
  Deleting a user reserves the retained runtime id for that principal so the
  runtime cannot be reassigned to a different same-tenant user while data is
  still retained. Admins may explicitly transfer a retained runtime to an
  existing same-tenant user or purge the retained runtime directory before
  releasing the runtime id for reuse.
- Gateway provider endpoint profiles are Gateway-owned reusable provider
  endpoints. They include a description, provider family, base URL, optional
  model allowlist, and a write-only API key. Discovery exposes them as virtual
  providers such as `endpoint:office-vllm`; Runtime resolves the virtual id into
  transient provider/base URL/key parameters without storing secrets in workflow
  JSON or browser storage.
- Hosted Flow, Code Web, and Observer use the server-configured Gateway URL on
  non-loopback UI hostnames. Browser-supplied Gateway URL changes are rejected
  unless the app-specific remote override is enabled behind access control.
  Host checks trust `Host` by default; forwarded host headers require an
  explicit trust-proxy env setting.
- Gateway workflow sharing uses the explicit workflow catalog, not another
  user's private `/bundles` directory. Catalog bundle versions are immutable,
  admins move default pointers and ACLs, and users start catalog workflows with
  `registry_scope: "tenant_catalog"` so the run executes in their own runtime.
  Catalog scope is explicit, direct private-bundle routes reject
  catalog-internal ids, and Gateway signs catalog workflow policy before
  passing it to Runtime.

## Start Here

- [README.md](README.md): Ecosystem overview and install paths.
- [docs/README.md](docs/README.md): Docs index for this repo.
- [docs/getting-started.md](docs/getting-started.md): Practical entry paths (core, runtime, gateway, UIs, bundles).
- [docs/architecture.md](docs/architecture.md): How the stack fits together.
- [docs/glossary.md](docs/glossary.md): Shared terminology used across docs.

## Scenarios

- [docs/scenarios/README.md](docs/scenarios/README.md): Scenarios index.
- [docs/scenarios/offline-coding-assistant.md](docs/scenarios/offline-coding-assistant.md): Local durable coding assistant.
- [docs/scenarios/gateway-first-local-dev.md](docs/scenarios/gateway-first-local-dev.md): Local gateway + web UIs.
- [docs/scenarios/specialized-agent-flow.md](docs/scenarios/specialized-agent-flow.md): Portable `.flow` agent across clients.
- [docs/scenarios/workflow-bundle-lifecycle.md](docs/scenarios/workflow-bundle-lifecycle.md): Publish/install/deprecate bundles.
- [docs/scenarios/phone-thin-client.md](docs/scenarios/phone-thin-client.md): iPhone via Web/PWA + gateway.
- [docs/scenarios/telegram-permanent-contact.md](docs/scenarios/telegram-permanent-contact.md): Telegram bridge + workflow.
- [docs/scenarios/email-inbox-agent.md](docs/scenarios/email-inbox-agent.md): Email bridge + workflow.

## Guides

- [docs/guide/README.md](docs/guide/README.md): Guides index.
- [docs/guide/deployment-topologies.md](docs/guide/deployment-topologies.md): Supported deployment patterns.
- [docs/guide/deployment-web.md](docs/guide/deployment-web.md): Browser UIs and gateway setup.
- [docs/guide/deployment-iphone.md](docs/guide/deployment-iphone.md): iPhone/PWA notes.
- [docs/guide/gateway-security.md](docs/guide/gateway-security.md): Safe gateway exposure defaults.
- [docs/guide/capability-routing-defaults.md](docs/guide/capability-routing-defaults.md): Provider/model/base URL defaults for input, output, embedding, and rerank routes.
- [docs/guide/workflow-bundles.md](docs/guide/workflow-bundles.md): `.flow` bundles and lifecycle.
- [docs/guide/agent-skills.md](docs/guide/agent-skills.md): Agent Skills (SKILL.md) proposal and how it composes with flows.
- [docs/guide/process-manager-env-vars.md](docs/guide/process-manager-env-vars.md): Write-only env var config from Observer.

## Release Profile (Pinned Versions)

- [pyproject.toml](pyproject.toml): Single source of truth for pinned ecosystem versions and extras.
- [abstractframework/__init__.py](abstractframework/__init__.py): `RELEASE_VERSIONS`, `get_release_profile()`, `print_status()`.

## Full Context

- [llms-full.txt](llms-full.txt): Concatenated context for copy/paste into an LLM (`python scripts/gen_llms_full.py`).

## Proposals / Research (non-canonical)

- [docs/backlog/overview.md](docs/backlog/overview.md): Root backlog index and active cross-package work.
- [docs/backlog/completed/0141_flow_browser_session_gateway_auth.md](docs/backlog/completed/0141_flow_browser_session_gateway_auth.md): Completed Flow browser-session Gateway auth isolation.
- [docs/backlog/planned/0142_gateway_tenant_isolation_and_shared_runtime.md](docs/backlog/planned/0142_gateway_tenant_isolation_and_shared_runtime.md): Planned Gateway tenant isolation and shared runtime design.
- [docs/backlog/planned/0143_shared_gateway_per_principal_runtime_router.md](docs/backlog/planned/0143_shared_gateway_per_principal_runtime_router.md): In-progress shared Gateway per-principal runtime router work.
- [docs/backlog/planned/gateway-control-plane/README.md](docs/backlog/planned/gateway-control-plane/README.md): Gateway admin/config/workflow-permission control-plane backlog track.
- [docs/backlog/proposed/gateway-control-plane/README.md](docs/backlog/proposed/gateway-control-plane/README.md): Proposed Explorer/Manager package-boundary follow-ups.
- [docs/backlog/completed/0154_multi_user_security_release_blockers.md](docs/backlog/completed/0154_multi_user_security_release_blockers.md): Completed multi-user release-blocking security fixes.
- [docs/backlog/completed/0157_gateway_provider_endpoint_profiles.md](docs/backlog/completed/0157_gateway_provider_endpoint_profiles.md): Completed Gateway-owned provider endpoint profiles and virtual `endpoint:*` discovery.
- [docs/backlog/proposed/gateway-control-plane/0155_hosted_proxy_shared_helper_extraction.md](docs/backlog/proposed/gateway-control-plane/0155_hosted_proxy_shared_helper_extraction.md): Proposed threshold for extracting shared hosted proxy helpers.
- [docs/backlog/planned/074_agent_skills_integration.md](docs/backlog/planned/074_agent_skills_integration.md): Backlog item for Agent Skills integration.
- [docs/backlog/planned/074_agent_skills_integration_plan.md](docs/backlog/planned/074_agent_skills_integration_plan.md): Phased plan for Agent Skills integration.
- [docs/skills/](docs/skills/): Research notes (spec links + ecosystem scan) for Agent Skills.
- [docs/claude/](docs/claude/): Research notes about Claude (non-Agent-Skills capability/skills scan).

## Optional

- [AbstractCore](https://github.com/lpalbou/abstractcore): LLM providers, tools, structured output, media.
- [AbstractRuntime](https://github.com/lpalbou/abstractruntime): Durable execution (runs, effects, waits, ledger, stores).
- [AbstractAgent](https://github.com/lpalbou/abstractagent): Agent patterns (ReAct/CodeAct/MemAct) built on runtime + core.
- [AbstractFlow](https://github.com/lpalbou/abstractflow): VisualFlow authoring and `.flow` bundles.
- [AbstractGateway](https://github.com/lpalbou/abstractgateway): HTTP/SSE control plane for gateway-first deployments.
- [AbstractCode](https://github.com/lpalbou/abstractcode): Terminal + web host UIs for durable runs.

--- pyproject.toml ---
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "abstractframework"
version = "0.1.6"
description = "Unified installer and documentation hub for the AbstractFramework ecosystem"
readme = "README.md"
license = {text = "MIT"}
authors = [
    {name = "Laurent-Philippe Albou", email = "contact@abstractcore.ai"}
]
keywords = [
    "agentic-os",
    "ai-agents",
    "llm",
    "autonomous-agents",
    "workflows",
    "multi-agent",
    "durable-execution",
    "knowledge-graph",
    "openai",
    "anthropic",
    "ollama",
    "local-llm"
]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Topic :: Scientific/Engineering :: Artificial Intelligence",
    "Typing :: Typed",
]
requires-python = ">=3.10"

# Base dependencies (remote-first, lightweight).
#
# Design constraints:
# - `pip install abstractframework` should default to *remote inference* (no MLX/vLLM/Diffusers local engine stacks).
# - Hardware-local stacks are opt-in via `abstractframework[apple]` and `abstractframework[gpu]`.
# - Keep the meta-package aligned with the real per-package profiles (especially `abstractgateway`).
dependencies = [
    # Gateway-first durable control plane (remote-light by default).
    "abstractgateway==0.2.23",

    # Workflow authoring + CLI app.
    "abstractflow==0.3.17",
    "abstractcode==0.3.8",
    "abstractassistant==0.4.8",

    # Pin the core Python stack for release determinism (also pulled transitively).
    "abstractcore==2.13.31",
    "AbstractRuntime==0.4.26",
    "abstractagent==0.3.10",
    "AbstractMemory==0.2.6",
    "abstractsemantics==0.0.4",

    # Capability plugins are remote-first by default; local runtimes live behind
    # their package-specific `apple`/`gpu` (or `all-*`) extras.
    "abstractvoice==0.10.17",
    "abstractvision==0.3.18",
    "abstractmusic==0.1.12",
]

[project.optional-dependencies]
# NOTE: Extras here are additive. The base install already pins and installs the
# full Python ecosystem; `apple`/`gpu` select hardware-local stacks and upgrade
# apps to their matching profiles.
#
# AbstractObserver is distributed as an npm package (`npx @abstractframework/observer`),
# so it is not installable via pip extras.

# Native macOS Python installs. These are intentionally not Docker profiles:
# MLX/Metal-backed engines run on the host Apple runtime. This profile upgrades
# the stack by selecting the hardware-local dependency aggregates (owned by Gateway),
# then adds user-facing apps.
apple = [
    "abstractgateway[apple]==0.2.23",
    "abstractflow[apple]==0.3.17",
    "abstractassistant[apple]==0.4.8; platform_system == \"Darwin\"",
]

gpu = [
    "abstractgateway[gpu]==0.2.23",
    "abstractflow[gpu]==0.3.17",
    "abstractassistant[gpu]==0.4.8",
]

[project.urls]
Homepage = "https://github.com/lpalbou/AbstractFramework"
Documentation = "https://github.com/lpalbou/AbstractFramework/tree/main/docs"
Repository = "https://github.com/lpalbou/AbstractFramework"
Issues = "https://github.com/lpalbou/AbstractFramework/issues"

[tool.setuptools.packages.find]
where = ["."]
include = ["abstractframework*"]

[tool.setuptools.package-data]
abstractframework = ["py.typed"]

[tool.black]
line-length = 100
target-version = ["py310", "py311", "py312"]

[tool.ruff]
line-length = 100

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]

[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true

[tool.pytest.ini_options]
testpaths = ["tests"]

--- abstractframework/__init__.py ---
"""
AbstractFramework unified distribution package.

This package provides:
- a single install entrypoint for the full AbstractFramework ecosystem
- lightweight helpers to inspect installed component versions

Most implementation functionality still lives in component projects.
"""

from __future__ import annotations

__version__ = "0.1.6"
__author__ = "Laurent-Philippe Albou"
__license__ = "MIT"

RELEASE_VERSIONS: dict[str, str] = {
    "abstractcore": "2.13.31",
    "abstractruntime": "0.4.26",
    "abstractagent": "0.3.10",
    "abstractflow": "0.3.17",
    "abstractcode": "0.3.8",
    "abstractgateway": "0.2.23",
    "abstractmemory": "0.2.6",
    "abstractsemantics": "0.0.4",
    "abstractvoice": "0.10.17",
    "abstractvision": "0.3.18",
    "abstractmusic": "0.1.12",
    "abstractassistant": "0.4.8",
}

CORE_DEFAULT_EXTRAS = [
    "remote",
    "tools",
    "media",
    "vision",
    "voice",
    "audio",
    "music",
]

# Convenience re-exports (AbstractCore is a base dependency of this meta-package).
# Keep this import lightweight: do not import optional tool/media deps here.
try:
    from abstractcore import GenerateResponse, create_llm  # type: ignore

    __all__ = [
        "CORE_DEFAULT_EXTRAS",
        "RELEASE_VERSIONS",
        "GenerateResponse",
        "create_llm",
        "get_installed_packages",
        "get_release_profile",
        "print_status",
    ]
except Exception:  # pragma: no cover
    __all__ = [
        "CORE_DEFAULT_EXTRAS",
        "RELEASE_VERSIONS",
        "get_installed_packages",
        "get_release_profile",
        "print_status",
    ]


def get_release_profile() -> dict[str, object]:
    """Return the pinned global release profile shipped by this package."""

    return {
        "abstractframework": __version__,
        "packages": RELEASE_VERSIONS.copy(),
        "core_extras": list(CORE_DEFAULT_EXTRAS),
        "install_profiles": {
            "base": "pip install abstractframework",
            "apple": 'pip install "abstractframework[apple]"',
            "gpu": 'pip install "abstractframework[gpu]"',
        },
    }


def get_installed_packages() -> dict[str, str]:
    """Return a dict of installed AbstractFramework Python packages and versions."""

    packages: dict[str, str] = {}

    def _maybe_add(import_name: str) -> None:
        try:
            mod = __import__(import_name)
            packages[import_name] = getattr(mod, "__version__", "installed")
        except Exception:
            return

    for name in [
        "abstractcore",
        "abstractruntime",
        "abstractagent",
        "abstractflow",
        "abstractcode",
        "abstractgateway",
        "abstractmemory",
        "abstractsemantics",
        "abstractvoice",
        "abstractvision",
        "abstractmusic",
        "abstractassistant",
    ]:
        _maybe_add(name)

    return packages


def print_status() -> None:
    """Print installation status of the main AbstractFramework Python packages."""

    installed = get_installed_packages()
    all_packages = [
        "abstractcore",
        "abstractruntime",
        "abstractagent",
        "abstractflow",
        "abstractcode",
        "abstractgateway",
        "abstractmemory",
        "abstractsemantics",
        "abstractvoice",
        "abstractvision",
        "abstractmusic",
        "abstractassistant",
    ]

    print("AbstractFramework installation status")
    print("=" * 40)

    for pkg in all_packages:
        if pkg in installed:
            print(f"  ✓ {pkg}: {installed[pkg]}")
        else:
            print(f"  ✗ {pkg}: not installed")

    print("")
    print(f"Installed: {len(installed)}/{len(all_packages)} packages")

    if len(installed) < len(all_packages):
        print("")
        print("To install the framework profile:")
        print("  pip install abstractframework")
        print("")
        print("Hardware-local profiles:")
        print('  pip install "abstractframework[apple]"')
        print('  pip install "abstractframework[gpu]"')

--- docs/README.md ---
# AbstractFramework documentation

**Write once. Generate everything.**

A modular, open-source ecosystem for building **durable, observable, multimodal** AI systems. Text, voice, image, video, music — one unified interface, any provider, any model, local or cloud.

This doc set focuses on two things:

1. **How to pick the right entry point** (AbstractCore SDK vs AbstractGateway control plane)
2. **How the pieces compose** (Core → Runtime → Gateway → Flow → Observer)

Most implementation lives in component repositories. This repo ships the `abstractframework` meta-package (a pinned install profile) and the cross-package docs you're reading now.

---

## Start here

### Choose your entry point

Start lightweight with just the LLM library, or go all-in with a production gateway. Both paths lead to the same ecosystem.

### AbstractCore (SDK + optional `/v1`)

Start with **AbstractCore**:

- 9+ providers with identical API (local + cloud)
- Universal tool calling, structured output, streaming
- Media handling (images, PDFs, audio, video)
- OpenAI-compatible HTTP server mode (`/v1`)
- Multimodal via capability plugins (Voice, Vision, Music)

Read **[Getting Started](getting-started.md)** → "Core-first" section.

### AbstractGateway (durable control plane)

Start with **AbstractGateway** + **AbstractFlow**:

- Durable execution that survives crashes and restarts
- Append-only ledger (replay-first) for auditability
- Scheduled workflows (cron-style, recurring)
- Multi-client: terminal, browser, tray, Telegram, email
- Start on one device, continue on another

Read **[Getting Started](getting-started.md)** → "Gateway-first" section.

---

## How the pieces fit (one picture)

```
Authoring                                Operations
──────────────────────────────────────────────────────────────

 AbstractFlow (author workflows)      AbstractGateway (control plane)
 + Flow Editor (web UI)               - run control + scheduling
 - exports .flow bundles              - bundle discovery + SSE ledger
               │                                │
               └─────────────┬──────────────────┘
                             ▼
          AbstractAgent (ReAct / CodeAct / MemAct)
                             │
                             ▼
                  AbstractRuntime (durable kernel)
                  - runs, effects, waits
                  - ledger + artifacts
                             │
                             ▼
                  AbstractCore (LLM + tools + media)
                  - provider abstraction + routing defaults
                  - capability plugins: voice / vision / music
```

---

## Doc map

| Page | What it covers |
|---|---|
| **[Getting Started](getting-started.md)** | The two entry points + first end-to-end run |
| **[Architecture](architecture.md)** | Layered model, durable execution primitives, honest comparisons |
| **[Configuration](configuration.md)** | Minimal config, where defaults live, Core vs Gateway |
| **[Glossary](glossary.md)** | Shared terminology (run, ledger, effect, wait, bundle, …) |
| **[FAQ](faq.md)** | Common questions, troubleshooting, comparisons |
| **[API](api.md)** | The `abstractframework` meta-package API (pins + helpers + re-exports) |

---

## Example apps

| App | What it does |
|---|---|
| **AbstractCode** | Terminal agentic dev client (local, durable sessions) |
| **AbstractAssistant** | macOS tray client (gateway-first, workflow picker, voice) |
| **AbstractObserver** | Browser UI to monitor, control, and schedule gateway runs |
| **Code Web UI** | Browser coding assistant (gateway-backed) |

---

## More docs

| Folder | What's inside |
|---|---|
| [docs/guide/](guide/) | Focused "how it works" notes |
| [docs/scenarios/](scenarios/) | End-to-end walkthroughs by use case |
| [docs/installers/](installers/) | Installer strategy and prototypes |
| [docs/comparisons/](comparisons/) | Trade-offs vs other frameworks |

--- docs/getting-started.md ---
# Getting started

This guide helps you build a correct mental model quickly, then run something end-to-end.

> **Write once. Generate everything.** Durable, observable, multimodal AI systems — one unified interface, any provider, any model, local or cloud.

AbstractFramework is a **stack**:

| Layer | Package | Role |
|---|---|---|
| SDK | **AbstractCore** | Provider/model abstraction, tools, structured output, media, embeddings |
| Agent patterns | **AbstractAgent** | Ready-made loops: ReAct (tool-first), CodeAct (code execution), MemAct (memory-enhanced) |
| Workflow authoring | **AbstractFlow** | Visual editor, portable `.flow` bundles, subflows |
| Durable kernel | **AbstractRuntime** | Runs, effects, waits, ledger, artifacts |
| Control plane | **AbstractGateway** | Persistence, scheduling, bundle discovery, SSE streaming |
| Operations | **AbstractObserver** | Browser UI to monitor, control, and schedule runs |

**Rule of thumb**: start with **Core** when you want a lightweight LLM library (SDK or `/v1`) for scripts/notebooks/apps; add **Gateway** when you need persistent runs, scheduling, and multi-client continuity.

> **Prerequisites**: Python 3.10+. Node.js 18+ (only for browser UIs). An LLM backend — local (Ollama, LM Studio, vLLM, llama.cpp) or cloud (OpenAI, Anthropic, etc.).

---

## Choose your entry point

| If you are… | Start with | Why |
|---|---|---|
| Calling LLMs/tools/media (SDK or OpenAI-compatible `/v1`) | **AbstractCore** | Lightweight, smallest surface area, fastest feedback loop |
| Building persistent agents/workflows (durable runs) | **AbstractGateway** + **AbstractFlow** | Durability, scheduling, bundle discovery, ledger replay/streaming |

You can also install the entire pinned ecosystem in one command:

```bash
pip install abstractframework
```

---

## Core-first: integrate via AbstractCore (SDK or `/v1`)

### 1. Install

```bash
pip install abstractcore
```

### 2. Configure a provider

**Local (Ollama)** — free, no API key:

```bash
ollama serve
ollama pull qwen3:4b-instruct
export OLLAMA_HOST="http://localhost:11434"
```

**OpenAI-compatible** (LM Studio, vLLM, LocalAI, llama.cpp):

```bash
export OPENAI_BASE_URL="http://127.0.0.1:1234/v1"
export OPENAI_API_KEY="local"
```

**Cloud APIs**:

```bash
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
```

**Or use the interactive wizard** (persists config to `~/.abstractcore/config/`):

```bash
abstractcore --config
abstractcore --status
```

### 3. Call the model

```python
from abstractcore import create_llm

llm = create_llm("ollama", model="qwen3:4b-instruct")
resp = llm.generate("Explain durable execution in 3 bullets.")
print(resp.content)
```

### What else you can do with Core

```python
# Tool calling
resp = llm.generate("What's the weather?", tools=[get_weather])

# Structured output (Pydantic)
report = llm.generate("Analyze this.", response_model=Report)

# Media input (images, audio, video, documents)
resp = llm.generate("Describe this image.", media=["photo.jpg"])

# Embeddings
vectors = llm.embed(["first document", "second document"])

# Streaming
for chunk in llm.generate("Write a poem.", stream=True):
    print(chunk.content or "", end="", flush=True)
```

---

## Gateway-first: durable runs + monitoring + scheduling

### 1. Install

```bash
pip install abstractgateway
```

### 2. Configure

```bash
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
export ABSTRACTGATEWAY_WORKFLOW_SOURCE=bundle
export ABSTRACTGATEWAY_DATA_DIR="$PWD/runtime/gateway"

# Optional: set only for a custom bundle registry. Packaged Gateway includes
# the shipped basic-agent bundle when this is unset.
# export ABSTRACTGATEWAY_FLOWS_DIR="$PWD/bundles"
```

### 3. Start the gateway

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

Verify:

```bash
curl -sS "http://127.0.0.1:8080/api/health"
```

### 4. Monitor runs with AbstractObserver

In another terminal:

```bash
npx @abstractframework/observer
```

Open http://localhost:3001 and connect. In hosted user-auth mode, enter Gateway
URL, Gateway user, and that user's token; Observer exchanges the token for a
browser session and does not persist the token in browser settings.

AbstractObserver is replay-first: it renders runs by replaying the ledger, then streams new steps live via SSE.

### 5. Schedule recurring work

Schedules are owned by the gateway (they survive restarts):

```bash
curl -X POST "http://127.0.0.1:8080/api/gateway/runs/schedule" \
  -H "Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"bundle_id":"my-bundle","flow_id":"my-entrypoint","start_at":"now","interval":"24h"}'
```

---

## Author orchestration with AbstractFlow

The ecosystem's distribution unit is a **workflow bundle** (`.flow` file): a VisualFlow graph + metadata. Gateways discover bundles and expose them to all clients.

### 1. Open the Flow Editor

With the gateway running:

```bash
npx @abstractframework/flow
```

Open http://localhost:3003 and connect to your gateway. In hosted user-auth
mode, use Gateway URL, Gateway user, and that user's token; Flow keeps an
opaque browser session instead of storing the token.

### 2. Build a workflow

- **On Flow Start** → takes input (prompt, provider, model, …)
- LLM steps, tool steps, branching, loops, subflows
- **On Flow End** → returns output (response, success, metadata)

To make it reusable across clients, implement an **interface contract** (for example `abstractcode.agent.v1` — a standard chat-like agent I/O contract).

### 3. Export and deploy

```bash
mkdir -p "$PWD/bundles"
cp my-agent.flow "$PWD/bundles/"
```

Start or restart Gateway with `ABSTRACTGATEWAY_FLOWS_DIR="$PWD/bundles"` when
you want that directory to be the active custom bundle registry. You can also
publish bundles through the Gateway API from AbstractFlow.

### 4. Run from any client

Once deployed, the bundle appears in:

- **AbstractObserver** — workflow picker / run launcher
- **AbstractAssistant** — workflow picker (per session)
- **Code Web UI** — workflow picker
- **Your own client** — via the gateway bundle discovery API

---

## Example apps

### AbstractCode (terminal)

A local dev client for agentic sessions — no server required:

```bash
pip install abstractcode
abstractcode --provider ollama --model qwen3:4b-instruct
```

Sessions are durable: close and reopen, your full context is preserved. Type `/help` for commands.

### AbstractAssistant (macOS tray)

Gateway-first by default. Select a workflow per session from the tray UI:

```bash
pip install abstractassistant
assistant tray
```

---

## Next steps

- **[Architecture](architecture.md)** — the layered model (Core / Runtime / Agent / Gateway / Flow / Observer)
- **[Configuration](configuration.md)** — where defaults live and how to configure them
- **[Glossary](glossary.md)** — shared terms (run, ledger, effect, wait, bundle, interface contract)
- **[FAQ](faq.md)** — comparisons, offline operation, troubleshooting

--- docs/architecture.md ---
# Architecture

AbstractFramework is open-source AI infrastructure built around one idea: **durable, observable execution** for AI workflows.

Most LLM frameworks optimize for prototyping speed. AbstractFramework optimizes for **operational reality**: workflows that pause/resume safely, runs that survive restarts, UIs that reconstruct state from history, and clear boundaries around tool execution and approvals.

---

## Choose your entry point

Start lightweight with just the LLM library, or go all-in with a production gateway. Both paths lead to the same ecosystem.

### AbstractCore (SDK + optional `/v1`)

Start here if you need a lightweight LLM library for scripts, notebooks, or existing applications. No infrastructure required — just install and call. Add multimodal capabilities with plugins as you grow.

- 9+ providers with identical API (local + cloud)
- Universal tool calling, structured output, streaming
- Media handling (images, PDFs, audio, video)
- OpenAI-compatible HTTP server mode (`/v1`)
- Multimodal via capability plugins (Voice, Vision, Music)

The right first step when you mainly care about calling models/tools/media (in-process via Python or via `/v1`) and want the smallest surface area.

### AbstractGateway (durable control plane)

Start here if you're building persistent AI applications — agents that run for hours, workflows that survive crashes, scheduled tasks. The gateway is your AI control plane: durable runs with ledger replay/streaming and thin clients that can attach/detach across devices.

- Durable execution that survives crashes and restarts
- Append-only ledger (replay-first) for auditability
- Scheduled workflows (cron-style, recurring)
- Multi-client: terminal, browser, tray, Telegram, email
- Start on one device, continue on another

The composition root when you need a control plane (local or remote).

---

## Layered view

```
Apps / UIs (thin clients)
──────────────────────────────────────────────────────
 AbstractObserver (monitor / control / schedule)
 Flow Editor (author workflows)
 Code Web UI, AbstractAssistant, your custom app
                       │  HTTP/SSE
                       ▼
AbstractGateway (control plane)
──────────────────────────────────────────────────────
 run lifecycle (start / resume / cancel)
 scheduling (durable, survives restarts)
 private bundle discovery + shared workflow catalog
 artifact + ledger serving / streaming
                       │
                       ▼
Composition layer
──────────────────────────────────────────────────────
 AbstractAgent: ReAct, CodeAct, MemAct patterns
 AbstractFlow: visual workflows → portable .flow bundles
                       │
                       ▼
Durable execution kernel
──────────────────────────────────────────────────────
 AbstractRuntime
 runs, effects, waits
 ledger (append-only history) + artifacts (large payloads)
                       │
                       ▼
LLM + tools + multimodality
──────────────────────────────────────────────────────
 AbstractCore
 provider/model abstraction + routing defaults
 tools, structured output, media input, embeddings, MCP
 capability plugins: voice / vision / music
```

**AbstractFlow** is the authoring/distribution layer: you design a VisualFlow graph, export a `.flow` bundle, and run it anywhere a compatible host exists.

**AbstractAgent** is the composition layer: ready-made agent loops (ReAct, CodeAct, MemAct) built on top of Runtime. These can be used standalone or inside a Flow as agent nodes.

---

## Durable execution primitives

These are the "why" behind the design — the properties that make the framework operationally useful.

### Run

A durable workflow instance with persisted state. Identified by a `run_id`.

### Ledger

The append-only history of a run: every step, effect, result, wait, and error is recorded.

This is what makes replay-first UIs possible: a client reconstructs state by replaying history, then follows along by streaming new events over SSE.

### Effects and waits

Work happens at explicit boundaries:

- An **effect** is a request for a side-effect (LLM call, tool call, ask user, wait-until, …).
- A **wait** is a checkpointed pause until external input arrives (tool results, user answer, a timer).

The key property: if a process dies while waiting, **the run is still correct**. Another process (or a restart) can resume it from the recorded wait.

### Artifacts

Large payloads (files, media, big tool results) are stored as **artifacts** and referenced by handle from JSON state and the ledger. This keeps state JSON-safe without losing evidence.

### Tool execution boundary

Tool **schemas** are durable (stored in the ledger). Tool **callables** are not (they live in the host process). This is intentional:

- Tool calls become explicit approval points (configurable per tool)
- Execution is auditable (arguments + results in the ledger)
- Runs remain restart-safe (the tool call is a wait, not an in-process function call)

---

## Workflow lifecycle: author → deploy → run → observe

### 1) Author with AbstractFlow

Build a workflow graph in the Flow Editor and export it as a `.flow` bundle.

### 2) Deploy the bundle

Copy bundles to `ABSTRACTGATEWAY_FLOWS_DIR`. The gateway discovers them automatically.

For hosted or multi-user gateways, admins can also promote immutable bundle
versions into the Gateway workflow catalog. The catalog owns shared/default
workflow pointers and ACLs; each catalog run still executes in the requesting
user's runtime unless a future explicit system-run mode is added.

### 3) Run from any client

Any gateway-backed client can: list bundles/entrypoints, start a run, attach to ledger replay/streaming, and resume waits (approvals, user input, tool results).

### 4) Observe and schedule with AbstractObserver

- Inspect any run (ledger replay)
- Watch a run live (SSE)
- Control runs (cancel, resume)
- Schedule recurring runs

---

## Multimodality

AbstractCore stays lightweight by treating modalities as **capability plugins** (discovered internally via Python entry points, then exposed via the AbstractCore SDK and its optional `/v1` endpoints; gateway-first deployments can also surface them through Gateway):

| Plugin | Capability | API surface |
|---|---|---|
| `abstractvoice` | TTS + STT | `llm.voice.tts(...)`, `llm.audio.transcribe(...)` |
| `abstractvision` | Image generation | `llm.vision.t2i(...)` |
| `abstractmusic` | Music generation | `llm.music.t2m(...)` |

Install a plugin; the API appears on your `llm` instance. Don't install it; Core stays small.

---

## How it compares (honest positioning)

### vs direct provider SDKs (OpenAI, Anthropic)

Direct SDKs are the right choice when you only use one provider and don't need durable orchestration.

AbstractCore adds value when you need: provider portability, consistent tool/structured-output behavior across backends, media policies, modality plugins, or a stable configuration layer that doesn't leak into app code.

### vs LangChain / LlamaIndex / PydanticAI

Those are primarily **in-process orchestration libraries**. AbstractFramework occupies a different niche: an **agentic OS-style** stack for durable, observable execution (runtime + append-only ledger + control plane), where the same workflows can run across providers, devices, and deployment modes.

**Where AbstractFramework is stronger**: durability and pause/resume as primitives, replay-first observability, portable `.flow` bundles that run across clients.

**Where others are stronger**: large connector/RAG ecosystems, minimal boilerplate for simple use cases, broader community examples.

### vs Temporal / Step Functions / job schedulers

AbstractGateway is architecturally closer to these systems, but specialized for LLM/tool loops: tool approval waits, AI-oriented artifacts, and replay-first thin-client UIs over HTTP/SSE.

---

## Where to go deeper

- **[Getting Started](getting-started.md)** — run Core-first or Gateway-first
- **[Configuration](configuration.md)** — minimal config, where defaults live
- **[Glossary](glossary.md)** — shared definitions (run, ledger, effect, wait, bundle, interface contract)
- Per-project architecture docs live in the component repositories

--- docs/configuration.md ---
# Configuration

This page answers two practical questions:

1. **What do I need to configure first to be productive?**
2. **Where do defaults live in a Core-first vs Gateway-first setup?**

Key principle: **Core owns model/provider defaults; Gateway owns durable execution and operations.**

---

## Core-first quick start

### Interactive wizard (recommended)

```bash
abstractcore --config      # guided setup — persists to ~/.abstractcore/config/
abstractcore --status      # show current config
abstractcore --install     # check readiness + download missing assets
```

The wizard walks through: default provider/model, base URLs, API keys, vision fallback, audio/video strategies, embeddings, and logging. Config is stored in `~/.abstractcore/config/abstractcore.json`.

### Manual environment variables

**Ollama** (local, free):

```bash
export OLLAMA_HOST="http://localhost:11434"
```

**OpenAI-compatible server** (LM Studio, vLLM, LocalAI, llama.cpp):

```bash
export OPENAI_BASE_URL="http://127.0.0.1:1234/v1"
export OPENAI_API_KEY="local"
```

**Cloud APIs**:

```bash
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
```

---

## Gateway-first quick start

### Required

```bash
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
```

For hosted or multi-user browser access, also enable Gateway user auth:

```bash
export ABSTRACTGATEWAY_USER_AUTH=1
```

The bootstrap token remains an admin/operator credential. Users sign in with a
Gateway user id and that user's token, then browser apps keep only an opaque
Gateway session. Gateway serves `/console` for account/runtime summary, admin
user management, optional user email metadata, token rotation, and capability
defaults selected from Gateway-discovered provider/model catalogs. Deleted users
leave retained runtime reservations; admins can transfer retained runtime data to
an existing same-tenant user or purge the retained runtime directory before
releasing the runtime id for reuse.

### Recommended (bundle-based workflows)

```bash
export ABSTRACTGATEWAY_WORKFLOW_SOURCE=bundle
export ABSTRACTGATEWAY_DATA_DIR="$PWD/runtime/gateway"

# Optional: set only for a custom bundle registry. When unset, Gateway uses
# the packaged shipped bundle directory containing basic-agent.
# export ABSTRACTGATEWAY_FLOWS_DIR="$PWD/bundles"
```

### Start

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

---

## Model/provider defaults (capability routes)

AbstractCore organizes defaults as **capability routes** — stable slots scoped by capability, not by application:

| Route | Meaning |
|---|---|
| `output.text` | Default text generation model |
| `input.text` | Default text understanding model |
| `embedding.text` | Default embeddings model |

### Set defaults in Core (single-host)

```bash
abstractcore --set-global-default ollama:qwen3:4b-instruct
```

### Set defaults through the Gateway (control plane)

In gateway-first deployments, set defaults via gateway tooling so the execution host stays consistent:

```bash
abstractgateway-config set-default output.text \
  --provider ollama \
  --model qwen3:4b-instruct
```

The gateway can update route defaults, but the default schema is Core-owned.
When Gateway user auth is enabled, the admin/default runtime overlay acts as the
Gateway baseline. Per-user writes through
`/api/gateway/config/capability-defaults/{kind}/{modality}` are stored under the
current user's runtime data plane and override the Gateway baseline only for
that user, so one user's provider/model defaults do not mutate another user's
defaults.

### Gateway provider endpoint profiles

Gateway Console also lets signed-in users create reusable provider endpoint
profiles. A profile stores a display name, description, provider family such as
`openai-compatible`, optional base URL, optional API key, capabilities, and an
optional model allowlist. The raw API key is write-only through the API/UI and is
not returned in discovery responses.

For OpenAI-compatible and other discoverable endpoints, use the console's model
discovery action to call the configured endpoint and populate the model picker.
Leaving all models unselected keeps live discovery active; selecting models
stores a fixed allowlist for that profile.

After creation, the profile appears in provider discovery as a virtual provider
id such as `endpoint:office-vllm`. Use that provider id in AbstractFlow nodes or
Gateway capability defaults, then select a discovered/allowed model normally.
At run time Gateway resolves the virtual provider into the real provider family,
base URL, and key for the current runtime call; workflow JSON and exported
bundles should not contain raw secrets.

---

## Storage and persistence

### Gateway data directory

`ABSTRACTGATEWAY_DATA_DIR` is the durability root:

- Run state
- Ledger history
- Artifacts (files, media, big payloads)
- Schedules

**Back up this directory** if you care about long-lived runs and audit trails.

### Optional SQLite backend

For production deployments, you can use SQLite for run metadata (artifacts stay file-backed):

```bash
export ABSTRACTGATEWAY_STORE_BACKEND=sqlite
export ABSTRACTGATEWAY_DB_PATH="$ABSTRACTGATEWAY_DATA_DIR/gateway.sqlite3"
```

### Core config directory

`~/.abstractcore/config/` stores persisted provider keys, base URLs, and defaults (written by `abstractcore --config`).

---

## Client configuration (Observer / Flow Editor / Code Web UI)

All gateway-backed browser UIs need two things:

- **Gateway base URL** (example: `http://127.0.0.1:8080`)
- **Gateway user + user token** in hosted user-auth mode

Local single-user tools can still use `ABSTRACTGATEWAY_AUTH_TOKEN` as an
operator token. Hosted browser apps should exchange user tokens for Gateway
browser sessions and should not store bearer tokens in browser storage.
AbstractFlow, AbstractCode Web, and AbstractObserver use this hosted
browser-session path when you provide a Gateway user id.

When these browser UIs are served from a non-loopback hostname, the Gateway URL
comes from the UI server configuration. Browser-supplied Gateway URL changes
are rejected unless the app-specific remote override is enabled behind your own
access control.

### AbstractObserver

```bash
npx @abstractframework/observer
```

Set Gateway URL, Gateway user, and that user's token in the UI
(http://localhost:3001). Observer exchanges the token for an app-scoped browser
session and does not persist the token in browser settings.

### Flow Editor

```bash
npx @abstractframework/flow
```

Optional convenience variable:

```bash
export ABSTRACTFLOW_GATEWAY_URL="http://127.0.0.1:8080"
```

### Code Web UI

```bash
npx @abstractframework/code
```

Set the gateway URL in the UI settings (http://localhost:3002).

---

## Multimodal capability plugins

Modalities are optional and become available when installed:

| Plugin | Capability | API surface |
|---|---|---|
| `abstractvoice` | Voice | `llm.voice` / `llm.audio` |
| `abstractvision` | Images | `llm.vision` |
| `abstractmusic` | Music | `llm.music` |

**Plugins are configured on the host that actually executes** (local app or gateway host), because that's where model downloads and hardware constraints apply.

---

## Per-project configuration references

This repo covers the overview. Each component repo owns its detailed configuration surface:

- **AbstractCore**: [centralized config](https://github.com/lpalbou/abstractcore/blob/main/docs/centralized-config.md), [prerequisites](https://github.com/lpalbou/abstractcore/blob/main/docs/prerequisites.md)
- **AbstractGateway**: [configuration](https://github.com/lpalbou/AbstractGateway/blob/main/docs/configuration.md), [security](https://github.com/lpalbou/AbstractGateway/blob/main/docs/security.md)
- **AbstractVoice**: [installation](https://github.com/lpalbou/abstractvoice/blob/main/docs/installation.md), [model management](https://github.com/lpalbou/abstractvoice/blob/main/docs/model-management.md)
- **AbstractVision**: [configuration](https://github.com/lpalbou/abstractvision/blob/main/docs/reference/configuration.md), [backends](https://github.com/lpalbou/abstractvision/blob/main/docs/reference/backends.md)

---

## Related docs

- **[Getting Started](getting-started.md)** — first run Core-first or Gateway-first
- **[Architecture](architecture.md)** — what lives where and why
- **[Glossary](glossary.md)** — capability routes, durable execution terms

--- docs/api.md ---
# API (meta-package)

This page documents the API exported by `abstractframework`, the meta-package shipped by this repository.

`abstractframework` is a **pinned distribution profile** plus a few lightweight helpers. AbstractFramework has two entrypoints: **AbstractCore** (LLM SDK + optional OpenAI-compatible `/v1` server) and **AbstractGateway** (durable run control plane over HTTP/SSE). Most functional APIs live in component packages — especially **AbstractCore** for the LLM SDK.

---

## Install

Full pinned ecosystem:

```bash
pip install abstractframework
```

Only the LLM SDK:

```bash
pip install abstractcore
```

Hardware-specific profiles (native installs, not Docker):

```bash
pip install "abstractframework[apple]"       # Apple Silicon native stack (MLX/Metal)
pip install "abstractframework[gpu]"         # GPU native stack (CUDA/ROCm)
```

---

## Convenience re-exports

`abstractframework` re-exports two common AbstractCore entry points so simple scripts can `from abstractframework import ...` without a separate `abstractcore` import.

### `create_llm`

```python
from abstractframework import create_llm

llm = create_llm("ollama", model="qwen3:4b-instruct")
resp = llm.generate("hello")
print(resp.content)
```

### `GenerateResponse`

The response type returned by `llm.generate(...)`.

---

## Release profile helpers

### `RELEASE_VERSIONS`

Dictionary mapping each ecosystem package name to the pinned version for this release.

### `CORE_DEFAULT_EXTRAS`

List of AbstractCore extras implied by the default framework install profile (remote-first): `remote`, `tools`, `media`, `vision`, `voice`, `audio`, `music`.

### `get_release_profile()`

Returns the full pinned profile metadata as a dict.

```python
from abstractframework import get_release_profile

profile = get_release_profile()
print(profile["abstractframework"])        # meta-package version
print(profile["packages"]["abstractcore"]) # pinned Core version
```

### `get_installed_packages()`

Returns a dict of installed AbstractFramework package versions detected in the current environment.

```python
from abstractframework import get_installed_packages
print(get_installed_packages())
```

### `print_status()`

Prints a human-readable status report of detected packages (installed vs missing).

```python
from abstractframework import print_status
print_status()
```

---

## Where to find the functional APIs

| What you need | Package |
|---|---|
| LLM calls, tools, structured output, media, embeddings, MCP | `abstractcore` |
| Durable execution kernel (runs, ledger, effects, waits) | `abstractruntime` |
| Agent patterns (ReAct, CodeAct, MemAct) | `abstractagent` |
| Control plane (HTTP server, scheduling, bundle discovery, SSE) | `abstractgateway` |
| Workflow authoring and `.flow` bundles | `abstractflow` |
| Monitoring / operations UI | `@abstractframework/observer` (npm) |

See **[Getting Started](getting-started.md)** for the two entry points and a first end-to-end run.

Gateway-hosted workflow APIs distinguish private runtime bundles from the
shared workflow catalog:

- `/api/gateway/bundles` remains the caller runtime's private bundle surface.
- `/api/gateway/workflow-catalog` lists catalog workflows visible to the signed
  in principal.
- `/api/gateway/admin/workflow-catalog/*` is admin-only for immutable catalog
  upload/promote/default/ACL/status operations.
- `/api/gateway/runs/start` and `/api/gateway/runs/schedule` accept
  `registry_scope: "tenant_catalog"` to start a catalog workflow in the
  requesting user's runtime.
- Catalog scope is explicit. Without `registry_scope`, Gateway starts only
  private runtime bundles. Catalog flow/schema inspection uses ACL-aware
  `/api/gateway/workflow-catalog/{bundle_id}/versions/{version}/flows/{flow_id}`
  routes.

Gateway-hosted user administration keeps retained runtime data explicit:

- `/api/gateway/admin/users` is the admin-only user list/create/read/update/delete
  surface.
- `/api/gateway/admin/runtime-reservations` lists retained runtime reservations
  left by deleted or reassigned users.
- `/api/gateway/admin/runtime-reservations/{runtime_id}/transfer` intentionally
  assigns retained runtime data to an existing same-tenant user.
- `/api/gateway/admin/runtime-reservations/{runtime_id}/purge` requires exact
  runtime-id confirmation, deletes the retained runtime directory, then releases
  the runtime id for reuse.

Gateway-hosted provider endpoint profiles make reusable hosted endpoints
discoverable without exposing raw keys:

- `/api/gateway/config/provider-endpoint-profiles` lists and creates profiles
  for the current principal.
- `/api/gateway/config/provider-endpoint-profiles/discover-models` previews the
  model list for a draft or saved profile by calling the configured provider
  family and base URL with the server-side or entered key. The response never
  echoes the raw key.
- `/api/gateway/config/provider-endpoint-profiles/{profile_id}` updates or
  deletes an existing profile. Gateway-scoped profiles require an admin
  principal.
- `/api/gateway/discovery/providers` includes enabled profiles as virtual
  providers such as `endpoint:office-vllm`.
- `/api/gateway/discovery/providers/{provider_name}/models` resolves virtual
  providers through the stored profile and returns the allowed or discovered
  model list without returning the raw API key.

--- docs/faq.md ---
# FAQ

## What is AbstractFramework?

An open-source ecosystem for building **durable, observable, multimodal AI systems**.

Two things share the name:

- **The ecosystem**: composable packages (Core, Runtime, Agent, Gateway, Flow, Observer, apps, modality plugins).
- **This repo / meta-package**: `abstractframework` is a pinned install profile + cross-package docs.

If you're looking for the main SDK, that's **AbstractCore**. If you need durable orchestration, that's **AbstractGateway**.

---

## Where should I start?

- **AbstractCore** — when you want direct LLM/tool/media integration with a clean, provider-agnostic API (Python SDK **or** OpenAI-compatible `/v1`).
- **AbstractGateway** — when you need durability, orchestration, scheduling, or language-agnostic access via HTTP/SSE routes.

Most teams start with Core (SDK or `/v1`), then introduce Gateway when workflows become long-running, scheduled, or shared across clients. See **[Getting Started](getting-started.md)**.

---

## Do I need to install the whole stack?

No.

| Goal | Install |
|---|---|
| Smallest useful (LLM SDK only) | `pip install abstractcore` |
| Gateway-first deployment | `pip install abstractgateway` |
| Everything at compatible versions | `pip install abstractframework` |

---

## Can I run everything offline with local models?

Yes. The core execution stack works fully offline with local model servers (Ollama, LM Studio, vLLM, llama.cpp, LocalAI). You need internet only to download models or use cloud APIs.

Multimodal plugins also work offline:

- **AbstractVoice**: Piper TTS (ONNX) + faster-whisper STT — prefetch once, run offline.
- **AbstractVision**: local Diffusers models or GGUF via stable-diffusion.cpp.
- **AbstractMusic**: local ACE-Step inference.

---

## What agent patterns are available?

AbstractAgent ships three patterns, all built on the durable Runtime kernel:

| Pattern | How it works |
|---|---|
| **ReAct** | Tool-first reasoning: observe → think → choose tool → execute → reflect |
| **CodeAct** | Code execution: generate Python, run it, observe output |
| **MemAct** | Memory-enhanced: reads/writes a knowledge graph during the loop |

Agents can run standalone or as nodes inside an AbstractFlow workflow.

---

## How does AbstractFramework compare to other frameworks?

### vs direct provider SDKs (OpenAI, Anthropic)

Direct SDKs are fine when you only use one provider and don't need durable orchestration.

AbstractCore adds value when you need: provider portability (local ↔ cloud), consistent tool/structured-output behavior across backends, media policies, modality plugins, or a configuration layer that doesn't leak into app code.

### vs LangChain / LlamaIndex / PydanticAI

Most agent libraries are **in-process orchestration**. AbstractFramework is a **durable orchestration stack**.

**Where AbstractFramework is stronger**: durability and pause/resume as primitives, replay-first observability, portable `.flow` bundles that run across clients.

**Where others are stronger**: large connector/RAG ecosystems, minimal boilerplate for simple use cases, broader community examples.

### vs Temporal / Step Functions / job schedulers

AbstractGateway is architecturally closer to these, but specialized for LLM/tool loops: tool approval waits, AI-oriented artifacts, and replay-first thin-client UIs over HTTP/SSE.

### Can I use AbstractFramework with LangChain/LlamaIndex?

Yes. Use AbstractFramework for orchestration and durability; integrate other libraries as tools or subflows:

- Use LlamaIndex retrievers as tools within an AbstractAgent
- Wrap LangChain chains as tool executors
- Let AbstractRuntime handle durability while external libraries handle specific capabilities

---

## What is a ".flow bundle" and why does it matter?

A `.flow` file is the portable distribution unit for workflows. It packages:

- A VisualFlow workflow graph
- Metadata (entry points, interfaces)
- Optional subflows and assets

Deploy a bundle to a gateway and any gateway-backed client can discover and run it.

---

## How do I author complex agentic orchestration?

1. Run a gateway (for durability + discovery).
2. Open the Flow Editor (`npx @abstractframework/flow`) and connect to the gateway.
3. Build a workflow: LLM steps, tool steps, agent nodes, branching, loops, subflows.
4. Export to `.flow`.
5. Copy into `ABSTRACTGATEWAY_FLOWS_DIR` to deploy.

To make it reusable across clients, implement an **interface contract** (for example `abstractcode.agent.v1`).

See **[Getting Started](getting-started.md)** → "Author orchestration with AbstractFlow".

---

## How do I monitor and schedule agentic work?

- **Monitoring**: use **AbstractObserver** — replay ledger, stream live execution, inspect errors, control runs.
- **Scheduling**: durable schedules are owned by the **gateway** (survive restarts). Create them from a client UI or via the gateway scheduling API.

See **[Getting Started](getting-started.md)** → "Gateway-first" section.

---

## How does multimodality work?

AbstractCore supports modalities via **capability plugins** (installed separately, discovered via entry points):

| Plugin | Capability |
|---|---|
| `abstractvoice` | `llm.voice` (TTS) / `llm.audio` (STT) |
| `abstractvision` | `llm.vision` (image generation) |
| `abstractmusic` | `llm.music` (text-to-music) |

Plugins are configured on the machine that actually executes (local app host or gateway host). Don't install a plugin; Core stays lightweight.

---

## Where is data stored?

- **Gateway**: `ABSTRACTGATEWAY_DATA_DIR` is the durability root (runs, ledger, artifacts, schedules).
- **Core config**: `~/.abstractcore/config/` (persisted by `abstractcore --config`).
- **Local apps**: typically `~/.abstractcode/`, `~/.abstractassistant/`, etc.

If you care about auditability and long-lived workflows, back up the gateway data directory.

---

## Troubleshooting

### Provider calls fail

- Verify provider environment variables (see **[Configuration](configuration.md)**).
- For local backends, make sure the server is running.
- Run `abstractcore --status` to check persisted config.

### Observer can't connect to the gateway

- Verify the gateway URL and auth token match.
- Ensure `ABSTRACTGATEWAY_ALLOWED_ORIGINS` includes the Observer origin (for local dev: `http://localhost:*`).
- Confirm the gateway is reachable: `curl http://127.0.0.1:8080/api/health`.

### Voice models not found

Prefetch explicitly (offline-first design):

```bash
abstractvoice-prefetch --stt small --piper en
```

--- docs/glossary.md ---
# Glossary

Shared terminology used across AbstractFramework documentation.

If you're new, read these groups first:

- **Durable execution**: run, ledger, effect, wait, artifact
- **Workflows**: flow, bundle, interface contract
- **Control plane**: gateway, schedule, observer

---

## Core (LLM SDK)

### Provider

An LLM backend integration (Ollama, OpenAI, Anthropic, any OpenAI-compatible server, etc.).

### Model

A provider-specific model identifier (`qwen3:4b-instruct`, `gpt-4o-mini`, `claude-3-5-sonnet-latest`, etc.).

### Capability route

A stable "slot" for a default model/provider choice, scoped by capability rather than by application. Examples: `output.text` (default text generation), `input.text` (default text understanding), `embedding.text` (default embeddings).

### Capability plugin

An optional package that extends AbstractCore with a modality API without bloating the base install. Install a plugin and the API appears on `llm` instances:

- `abstractvoice` → `llm.voice` (TTS) / `llm.audio` (STT)
- `abstractvision` → `llm.vision` (image generation)
- `abstractmusic` → `llm.music` (text-to-music)

---

## Tools

### Tool spec (schema)

A JSON-serializable description of a tool: name, description, and input schema. Tool specs are durable — they can be stored in the ledger and replayed.

### Tool executor (callable)

The host-side implementation that actually runs a tool. Executors are **not** durable; they live in the process that owns tool execution.

### Approval boundary

By default, tool execution is gated behind an explicit approval/resume step. This makes tool side-effects auditable, controllable, and restart-safe. Approval policy is configurable per tool (auto-approve safe tools, require manual approval for mutations).

---

## Durable execution (Runtime)

### Run

A durable workflow instance, identified by a `run_id`. A run has persisted state and a full append-only history.

### Session ID

A stable identifier used to group multiple runs into a long-lived "session" across time and clients (a chat thread, a device session, etc.).

### Ledger

The append-only history of what happened in a run (steps, effects, results, waits, errors). Replay-first clients render by replaying the ledger and then streaming new events.

### Step

One recorded unit in the ledger (node transitions, effect requests, results, errors).

### Effect

A typed request for a side-effect (LLM call, tool calls, ask user, wait-until, …). Effects are recorded so a run can resume correctly after restarts.

### Wait

A durable pause point: the run is checkpointed and stops progressing until it is resumed with external input (tool results, user input, time, or an event).

### Artifact

A file- or store-backed blob referenced from JSON state/ledger. Used for large payloads (files, media, big tool results) to keep state JSON-safe while preserving evidence.

---

## Agent patterns

### Agent

A runtime workflow that implements a reasoning loop: observe → think → act → repeat. AbstractAgent ships three patterns:

- **ReAct**: tool-first reasoning (observe environment, choose tool, execute, reflect)
- **CodeAct**: code execution (generate Python, execute, observe output)
- **MemAct**: memory-enhanced (read/write a knowledge graph during the loop)

Agents can run standalone or as nodes inside a Flow.

---

## Workflows (Flow)

### Flow

A workflow graph: nodes + edges + state transitions. Flows encode orchestration logic: LLM steps, tool steps, branching, loops, subflows, and agent nodes.

### VisualFlow

The JSON workflow graph format used by AbstractFlow and executed by AbstractRuntime.

### Workflow bundle (`.flow`)

A portable distribution unit that packages a VisualFlow graph plus metadata (and optionally subflows/assets). Gateways discover `.flow` bundles and expose them to clients.

### Interface contract

A versioned input/output contract a flow can implement so multiple clients can run it consistently (for example `abstractcode.agent.v1` for chat-like agent flows).

---

## Control plane (Gateway) + operations (Observer)

### Gateway

The control plane for durable runs: start/resume/cancel, persistence, scheduling, bundle discovery, and ledger serving/streaming over HTTP/SSE.

### Schedule

A durable recurring trigger owned by the gateway ("run this workflow every 24h"). Schedules survive restarts.

### Observer

A thin-client browser UI for operations: monitor runs, inspect ledger history, watch live execution, control runs, and (when enabled) create schedules.

---

## Memory

### Active context

The current message view sent to the model (what the LLM "sees"). A derived view that can be compacted without losing underlying history.

### Stored history

The durable record of what happened (ledger + artifacts). The source of truth.

### Knowledge graph (KG) memory

Long-term memory stored as temporal triples (AbstractMemory), validated through the shared semantics registry (AbstractSemantics). Optional — not a hard dependency of the runtime kernel.

--- docs/scenarios/README.md ---
# Scenarios

This section is use-case oriented. Each scenario is an end-to-end path with concrete commands and "what to expect".

- [Offline coding assistant (terminal)](offline-coding-assistant.md)
- [Gateway-first local development](gateway-first-local-dev.md)
- [Specialized agent as a portable `.flow`](specialized-agent-flow.md)
- [Workflow bundle lifecycle (publish/install/deprecate)](workflow-bundle-lifecycle.md)
- [Telegram permanent contact](telegram-permanent-contact.md)
- [Email inbox agent](email-inbox-agent.md)
- [Phone thin client (iPhone via Web/PWA)](phone-thin-client.md)

If you prefer component-first docs, start with [Getting Started](../getting-started.md).

--- docs/scenarios/offline-coding-assistant.md ---
# Scenario: Offline Coding Assistant (Terminal)

Goal: run a durable coding assistant locally, offline-first, with Ollama (or an OpenAI-compatible local server).

## Prereqs

- Python 3.10+
- An LLM backend:
  - Ollama (recommended)
  - LM Studio / vLLM / LocalAI (OpenAI-compatible)

## Step 1: Install

Minimal install:

```bash
pip install abstractcode
```

Full pinned stack (includes AbstractCode):

```bash
pip install abstractframework
```

## Step 2: Start a local model

### Ollama

```bash
ollama serve
ollama pull qwen3:4b-instruct
export OLLAMA_HOST="http://localhost:11434"
```

## Step 3: Run AbstractCode

```bash
abstractcode --provider ollama --model qwen3:4b-instruct
```

## Step 4: Work with files and tools

- Mention files in prompts with `@path/to/file`.
- Type `/help` for commands.
- Tools are approval-gated by default:
  - Toggle in-session: `/auto-accept`
  - Start with: `--auto-approve`

## What "durable" means here

- Closing and reopening the app keeps state.
- Default storage:
  - `~/.abstractcode/state.json` (UI snapshot)
  - `~/.abstractcode/state.d/` (durable run state + ledger + artifacts)
- Start fresh: `/clear`
- Disable persistence: `--no-state`

## When to switch to the Gateway path

Use a gateway when you want:
- multiple thin clients observing the same run
- remote execution
- scheduling and a durable command inbox
- bundle discovery for specialized agents

See [Gateway-first local development](gateway-first-local-dev.md).

--- docs/scenarios/gateway-first-local-dev.md ---
# Scenario: Gateway-first Local Development

Goal: run the full "thin clients + gateway control plane" stack locally:

- AbstractGateway (HTTP/SSE control plane)
- AbstractObserver (run observability)
- AbstractFlow Editor (author `.flow` workflows)
- Code Web UI (browser coding assistant)

This is the recommended topology because execution is unified and clients can attach/detach freely.

## Step 0: Install the pinned stack (recommended)

```bash
pip install abstractframework
```

From a source checkout, `./scripts/gateway-flow-local.sh` starts Gateway and
Flow together and prints the default `admin` browser-login token. For a
published-package smoke run, `./scripts/gateway-flow.sh` creates an isolated
published-package venv, enables Gateway user auth, prepares the same `admin`
user, and prints the Gateway URL, user, and token to enter in Flow.

If you want a minimal install instead, you need at least:
- `abstractgateway`
- `abstractflow` (and optionally `abstractflow[agent]` if your bundles use Agent nodes)

## Step 1: Prepare directories

Pick the Gateway data folder. Packaged Gateway installs already include the
shipped `basic-agent` bundle. In a source checkout, point the gateway at the
repo's bundled workflows.

- `DATA_DIR`: where gateway stores run state/ledger/artifacts
- `FLOWS_DIR`: optional custom `.flow` bundle directory; in this repo use
  `./abstractgateway/flows/bundles`

Example:

```bash
mkdir -p ./runtime/gateway
```

## Step 2: Configure the gateway

```bash
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export ABSTRACTGATEWAY_USER_AUTH=1
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
export ABSTRACTGATEWAY_DATA_DIR="$PWD/runtime/gateway"

# Source checkout only. Packaged installs can omit this and use the shipped bundle path.
export ABSTRACTGATEWAY_FLOWS_DIR="$PWD/abstractgateway/flows/bundles"
```

Optional route defaults (if your flows use LLM nodes):

```bash
abstractgateway-config set-default output.text \
  --provider ollama \
  --model qwen3:4b-instruct
```

You can also set the text default through Core:

```bash
abstractcore --set-global-default ollama/qwen3:4b-instruct
```

Capability routes are the durable default surface for local setups.

## Step 3: Start the gateway

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

Smoke check:

```bash
curl -sS http://127.0.0.1:8080/api/health
```

Create a local user token for browser UIs:

```bash
curl -sS -X POST http://127.0.0.1:8080/api/gateway/admin/users \
  -H "Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"tenant_id":"default","user_id":"admin","runtime_id":"default","roles":["admin","user"]}' \
  | python -m json.tool
```

## Step 4: Start the thin clients

In separate terminals:

```bash
npx @abstractframework/observer
npx @abstractframework/flow
npx @abstractframework/code
```

Default ports:
- Observer: http://localhost:3001
- Code Web: http://localhost:3002
- Flow Editor: http://localhost:3003

## Step 5: Connect UIs to the gateway

In each UI:
- Set Gateway URL: `http://127.0.0.1:8080`
- Set User: `admin`
- Paste the generated Gateway user token
- Sign in

## Step 6: Author and run a specialized agent

1. In Flow Editor, create a workflow implementing `abstractcode.agent.v1`.
2. Export as a `.flow` bundle.
3. Put the `.flow` file into `FLOWS_DIR` (or configure the editor to publish to the gateway).
4. In Observer or Code Web, pick the workflow and start a run.
5. Watch the ledger stream in Observer.

See [Specialized agent as a portable `.flow`](specialized-agent-flow.md).

## Troubleshooting

- CORS errors in browser: widen `ABSTRACTGATEWAY_ALLOWED_ORIGINS` for your UI origin.
- "Unauthorized": ensure the browser UI is signed in with a Gateway user token, not the admin token.
- Bundles not showing up: verify `ABSTRACTGATEWAY_FLOWS_DIR` contains the shipped `basic-agent` bundle and any custom `.flow`
  files, then reload bundles from the UI (or restart the gateway).

--- docs/scenarios/specialized-agent-flow.md ---
# Scenario: Specialized Agent as a Portable `.flow`

Goal: build a specialized agent once, then run it in:

- AbstractCode (terminal)
- Code Web UI (browser)
- AbstractObserver (browser)
- your own apps (via gateway bundle discovery)

The key is an interface contract: `abstractcode.agent.v1`.

## Step 1: Create the flow

In the Flow Editor (`npx @abstractframework/flow`):

1. Add an **On Flow Start** node.
2. Add an **Agent** node (or **LLM Call** for a single-shot step).
3. Add an **On Flow End** node.
4. Wire the pins:
   - Start outputs to Agent inputs: `provider`, `model`, `prompt` (and optional `tools`, `context`, `memory`)
   - Agent outputs to End inputs: `response`, `success`, `meta` (and optional `scratchpad`)
5. In flow properties, set:
   - `interfaces: ["abstractcode.agent.v1"]`

## Agent vs LLM Call

- Use **Agent** when you want an internal multi-step loop (ReAct/CodeAct/MemAct style).
- Use **LLM Call** when you want a single request/response and explicit tool wiring in the graph.

See [Guide: Agent vs LLM Call](../guide/agent-vs-llm.md).

## Step 2: Export as a bundle

Export the workflow as a `.flow` bundle.

A `.flow` bundle packages:
- the root VisualFlow JSON
- any referenced subflows
- optional assets

## Step 3: Run locally (terminal)

With AbstractCode:

```bash
abstractcode --workflow /path/to/my-agent.flow
```

Or install the bundle into the local registry:

```bash
abstractcode workflow install /path/to/my-agent.flow
abstractcode --workflow my-agent
```

## Step 4: Deploy to a gateway

Copy the `.flow` bundle into `ABSTRACTGATEWAY_FLOWS_DIR`.

Then it will appear in:
- Observer workflow picker
- Code Web UI workflow picker
- Gateway discovery endpoints

## Step 5: Pass memory (optional)

If you want KG memory recall/writeback, wire a `memory` object into the Agent/LLM Call node.

See [Guide: Flow + KG memory](../guide/flow-and-kg-memory.md).


--- docs/scenarios/workflow-bundle-lifecycle.md ---
# Scenario: Publish, Install, and Deprecate Workflows (`.flow` bundles)

Goal: author a workflow once, distribute it as a portable `.flow` bundle, and manage its lifecycle on a gateway so it is
discoverable across clients.

## What you're managing

AbstractFramework distributes workflows as WorkflowBundles (`.flow` files):
- a zip bundle containing `manifest.json` + `flows/*.json` (and optional assets)
- entrypoints can advertise interface contracts (for example `abstractcode.agent.v1`) for discovery across clients

## Step 1: Author the workflow (Flow Editor)

Run the editor UI:

```bash
npx @abstractframework/flow
```

Open http://localhost:3003 and create/update your workflow.

## Step 2: Export/publish a `.flow` bundle

In the editor, export a `.flow` file (the bundle includes the root flow plus referenced subflows).

## Step 3: Put the bundle where the gateway loads bundles

On the gateway host, configure:

```bash
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/workflows"   # directory containing *.flow
export ABSTRACTGATEWAY_DATA_DIR="/path/to/gateway-data" # durable stores (run, ledger, artifacts)
```

Copy your bundle into `ABSTRACTGATEWAY_FLOWS_DIR`, for example:

- `my-bundle@0.1.0.flow`

Start/restart the gateway (bundle mode is the default):

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

## Step 4: Discover and run from clients

Once loaded, the bundle entrypoints show up in:
- Observer workflow picker
- Code Web UI workflow picker
- Gateway discovery endpoints (for custom clients)

If you built a chat-like agent flow, declare `interfaces: ["abstractcode.agent.v1"]` so clients can run it as an agent.

## Step 5: Deprecate instead of deleting (recommended)

Deprecation hides workflows from discovery and blocks new starts, while keeping installed bundles for:
- reproducibility of past runs
- auditability and traceability

Look for gateway lifecycle controls in your UI client (Observer / Flow Editor), or use the gateway API if needed.


--- docs/scenarios/telegram-permanent-contact.md ---
# Scenario: Telegram "Permanent Contact" (Gateway Bridge + Agent Workflow)

Goal: run a Telegram contact that forwards inbound Telegram messages to a durable workflow (one run per message) and sends
replies back to Telegram.

This is a gateway-first scenario: the gateway host owns durability and stores plaintext history for replay/observability.

## High-level architecture

1. Telegram bridge receives a message.
2. Gateway maps it to a stable `session_id` (typically `telegram:<chat_id>:r<rev>`).
3. Gateway starts a new run for the configured flow (thin-client semantics).
4. The bridge sends the run output back to Telegram.

## Security model choices

Telegram has two integration paths:

1. TDLib + Secret Chats (E2EE in transit; recommended)
2. Bot API (easy, not E2EE)

Even with E2EE, messages are decrypted on the gateway host and persisted to the durable stores in plaintext by design.
Secure the gateway host and its storage.

## Step 1: Install AbstractGateway (Telegram bridge)

```bash
pip install abstractgateway
# Optional (only if your workflows call Telegram tools like `send_telegram_message`):
# pip install "abstractcore[tools]"
```

## Step 2: Configure the gateway (minimum)

You need a normal gateway configuration plus Telegram bridge settings. At minimum:

```bash
# Bundles (*.flow). Include the shipped `basic-agent` bundle (and any custom bundles).
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/bundles"
export ABSTRACTGATEWAY_AUTH_TOKEN="..."  # required
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
export ABSTRACTGATEWAY_DATA_DIR="$PWD/runtime/gateway"

# Tool execution + approvals:
# - `approval` (default): safe tools run in-process; dangerous/unknown tools require a Telegram reply: `/approve` or `/deny`.
export ABSTRACTGATEWAY_TOOL_MODE="approval"

export ABSTRACT_TELEGRAM_BRIDGE=1
# Bot API (easy, not E2EE). If ABSTRACT_TELEGRAM_BOT_TOKEN is set, transport defaults to bot_api.
export ABSTRACT_TELEGRAM_BOT_TOKEN="..."      # from @BotFather
# Optional: TDLib (E2EE) instead of Bot API:
# export ABSTRACT_TELEGRAM_TRANSPORT="tdlib"
# Optional: override which workflow to run per message.
# Default (when unset): shipped `basic-agent` bundle entrypoint.
# export ABSTRACT_TELEGRAM_BUNDLE_ID="basic-agent"
# export ABSTRACT_TELEGRAM_FLOW_ID="81795ea9"

# Access control (required by default)
# Use /whoami in Telegram to discover your numeric user_id.
export ABSTRACT_TELEGRAM_ALLOWED_USERS="123456789"

# Optional: pairing mode (lets unknown users request access, but requires an admin):
# export ABSTRACT_TELEGRAM_DM_POLICY="pairing"
# export ABSTRACT_TELEGRAM_ADMIN_USERS="123456789"

# Optional: group chat support (disabled by default):
# export ABSTRACT_TELEGRAM_GROUP_POLICY="allowlist"
# export ABSTRACT_TELEGRAM_ALLOWED_CHATS="-100123456789"  # use /whoami inside the group to discover chat_id
# export ABSTRACT_TELEGRAM_REQUIRE_MENTION_IN_GROUPS=1     # default true
```

Then start the gateway:

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

Notes:
- Default LLM routing comes from the execution-host `output.text` capability route. Set it with
  `abstractcore --set-global-default ...` or `abstractgateway-config set-default output.text ...`.
- Telegram-only routing override: set `ABSTRACT_TELEGRAM_MODEL="..."` (and optionally `ABSTRACT_TELEGRAM_PROVIDER="..."`) without changing other gateway traffic.
- Durable history limit: `ABSTRACT_TELEGRAM_MAX_HISTORY_MESSAGES` (default: 30).
- STT fallback and vision caption fallback are configured via `abstractcore --config` (audio strategy + vision fallback).
- `/reset` clears the durable session; optional best-effort message deletion is controlled by `ABSTRACT_TELEGRAM_RESET_DELETE_MESSAGES` and `ABSTRACT_TELEGRAM_RESET_DELETE_MAX`. The confirmation text is configurable via `ABSTRACT_TELEGRAM_RESET_MESSAGE`.
- For tool approvals, the bridge will prompt you in chat; reply with `/approve` to run tools, or `/deny` to cancel.

## Step 3: Workflow wiring

Telegram is a thin client: any workflow that reads `prompt`/`context` (like `abstractcode.agent.v1`) and writes a string
to `run.output.answer` or `run.output.response` will work. Durable memory comes from the Telegram `session_id`.

## Step 4: TDLib (E2EE) bootstrap (recommended path)

TDLib requires a real Telegram user account and the TDLib shared library (`tdjson`) installed on the gateway host. You
then authenticate once to create a persistent TDLib session directory.

Because TDLib setup is platform-specific, follow:
- [Guide: Telegram integration](../guide/telegram-integration.md)

## Step 5: Test

Send a Telegram message to the AI contact. You should see:
- gateway emits the event into the session
- your run progresses and sends a reply via tools
- Observer can replay the ledger for the session/run

## See also

- [Guide: Telegram integration](../guide/telegram-integration.md) — configuration and TDLib details

--- docs/scenarios/email-inbox-agent.md ---
# Scenario: Email Inbox Agent (IMAP Bridge + SMTP Replies)

Goal: ingest inbound emails as durable events and let a workflow reply (or take actions) with framework-native email tools.

## High-level architecture

- Inbound: gateway email bridge polls IMAP, stores raw + attachments as artifacts, emits `email.message` events into a
  stable `session_id` per thread.
- Outbound: workflows call `send_email` with centralized SMTP defaults (no repeating host/user per tool call).

## Step 1: Configure email accounts on the tool-execution host

Email tools are account-scoped: IMAP/SMTP host/user are configured on the process that executes tools (gateway local
tools, CLI host, or a tool worker).

For the full configuration matrix (env vs YAML vs AbstractCore config), use the canonical guide in the main framework
workspace:
- [Guide: Email integration](../guide/email-integration.md)

## Step 2: Enable the inbound email bridge on the gateway host

Minimum env vars (plus your email account config):

```bash
export ABSTRACT_EMAIL_BRIDGE=1
export ABSTRACT_EMAIL_POLL_SECONDS=60

export ABSTRACT_EMAIL_FLOW_ID="<bundle_id>:<flow_id>"   # autostart/attach a workflow per thread/session
```

Start the gateway with a persistent `ABSTRACTGATEWAY_DATA_DIR` so bridge state survives restarts.

## Step 3: Wire the workflow

Create a workflow that:
1. handles the `email.message` event
2. reads `payload.email.*` (subject/from/body and artifact-backed attachments)
3. optionally opens attachments via `open_attachment(artifact_id=...)`
4. replies with `send_email(to=..., subject=..., body_text=...)`

## Step 4: Test

Send an email into the mailbox. Expected:
- the bridge emits `email.message`
- a session-run starts (or is resumed) for that thread
- your workflow replies via `send_email`

--- docs/scenarios/phone-thin-client.md ---
# Scenario: Phone Thin Client (iPhone via Web/PWA) + Gateway

Goal: run a thin client UI on a phone that attaches to runs and controls them, while the gateway host owns durability and
execution.

This is especially useful for:
- remote coding/agent sessions from a phone
- observing runs while away from your workstation

## Mental model (thin client)

- The phone does not tick the runtime.
- It renders by replaying/streaming the ledger.
- It acts by sending durable commands (resume/pause/cancel/emit_event).

## Quickstart (LAN dev, no HTTPS)

1. Run the gateway bound to all interfaces (still use auth):
   - `abstractgateway serve --host 0.0.0.0 --port 8080`
2. Run the web UI host on all interfaces (dev server):
   - `npx @abstractframework/code`
3. Allow the dev origin in gateway CORS/origin allowlist.
4. Open the web UI URL on your iPhone Safari and connect it to the gateway.

## Production note (recommended)

For installable iOS PWA behavior, host the web UI over HTTPS and run the gateway behind HTTPS termination (reverse proxy
or tunnel). Restrict `ABSTRACTGATEWAY_ALLOWED_ORIGINS` to the exact UI origin.

## Canonical iPhone guide (deeper)

For a step-by-step iPhone/PWA guide, see:
- [Guide: Web deployment](../guide/deployment-web.md)
- [Guide: iPhone notes](../guide/deployment-iphone.md)

--- docs/guide/README.md ---
# Guides

Short, focused guides for common framework questions.

- [Agent vs LLM Call (VisualFlow)](agent-vs-llm.md)
- [Capability plugins (voice/audio/vision)](capability-plugins.md)
- [Capability routing defaults](capability-routing-defaults.md)
- [Deployment topologies](deployment-topologies.md)
- [Web deployment (browser UI + gateway)](deployment-web.md)
- [iPhone notes (Safari / PWA)](deployment-iphone.md)
- [Gateway exposure security](gateway-security.md)
- [Runtime scope (run/session/global/all)](runtime-scope.md)
- [Flow + KG memory (memory object)](flow-and-kg-memory.md)
- [Scheduled workflows (durable jobs)](scheduled-workflows.md)
- [Prompt caching (prompt/KV)](prompt-caching.md)
- [Agent Skills (SKILL.md) — proposal](agent-skills.md)
- [WorkflowBundles (`.flow`) lifecycle](workflow-bundles.md)
- [Telegram integration](telegram-integration.md)
- [Email integration](email-integration.md)
- [Process manager env vars (write-only)](process-manager-env-vars.md)

--- docs/guide/agent-vs-llm.md ---
# Agent vs LLM Call (VisualFlow)

VisualFlow has two LLM-oriented nodes that intentionally look similar, but differ in **autonomy**.

## When to use which

### Use **LLM Call**

- You want a **single** LLM request/response step (no internal loop).
- You want to explicitly wire tool execution in the graph:
  - `LLM Call.tool_calls` -> `Tool Calls.tool_calls` -> (your next node).

### Use **Agent**

- You want the node to run an **internal multi-step loop** (ReAct-style) until it finishes or hits a cap.
- You want a runtime-owned **scratchpad** (trace/transcript) for observability.

## Inputs (shared contract)

Agent and LLM Call share the same parameter set and ordering (Agent has one extra cap: `max_iterations`):

1. `use_context` (boolean): include the run's active context messages (`context.messages`) in the request.
2. `context` (object): explicit context override. When provided, `context.messages` overrides inherited run context
   messages.
3. `provider` (provider), `model` (model): route the call.
4. `system` (string): optional system instructions for this node.
5. `prompt` (string): the user prompt/content for this node.
6. `tools` (tools): allowlist of tools the model may request (execution is still explicit in the graph).
7. Agent-only: `max_iterations` (number): maximum internal loop iterations (safety cap).
8. `max_in_tokens` (number): optional per-call/per-agent input token budget (VisualFlow shorthand for
   `max_input_tokens`).
9. `temperature` (number), `seed` (number): sampling controls.
10. `resp_schema` (object): optional JSON Schema for schema-constrained responses.

Notes:
- The canonical prompt key/pin is always `prompt` (there is no `request` alias).

## Outputs (what differs)

### LLM Call outputs

- `response` (string), `success` (boolean), `meta` (object), `tool_calls` (array)

### Agent outputs

- `response` (string), `success` (boolean), `meta` (object), `scratchpad` (object)

There is no separate `result` output pin in the durable contract.

### Agent `scratchpad` (what it contains)

The Agent scratchpad is runtime-owned observability (it can be large). Common fields:

- `messages`: agent-internal transcript for the sub-run (ReAct loop)
- `task`: the agent prompt/task for this node
- `context_extra`: any extra fields passed in `context` besides `task`/`messages` (host-defined)
- `node_traces` / `steps`: structured per-node trace + flattened UI-friendly steps
- `tool_calls` / `tool_results`: best-effort extraction from the trace

## `resp_schema` (structured responses)

When `resp_schema` is provided:

- `response` is a JSON string matching the schema (so it stays a simple `string` pin).
- Use a JSON parser node if you want to treat it as an object downstream.

## RunnableFlow interface (for chat-like clients)

The RunnableFlow (v1) interface (id: `abstractcode.agent.v1`) is the host contract used by AbstractCode, AbstractObserver,
and similar clients:

- `On Flow Start` exposes the same parameter set (in the same order) so hosts can configure a workflow run.
- Required `On Flow Start` pins: `provider`, `model`, `prompt` (everything else optional).
- Required `On Flow End` pins: `response`, `success`, `meta` (others optional).


--- docs/guide/capability-plugins.md ---
# Capability plugins (Voice/Audio/Vision/Music)

This guide explains how to add optional audio/voice/vision capabilities to AbstractFramework without turning
`abstractcore` into a kitchen sink.

## Mental model (two concepts; don't mix them)

1. **LLM input modalities (AbstractCore)**
   - Attaching image/audio/video to an LLM call (`generate(..., media=[...])`) depends on the selected provider/model's
     input capabilities.

2. **Deterministic capabilities (plugins)**
   - STT/TTS and generative vision are deterministic APIs that can be used with or without an LLM call:
     - `core.voice` / `core.audio` (speech-to-text, text-to-speech) via `abstractvoice`
     - `core.vision` (text-to-image, image-to-image, ...) via `abstractvision`
     - `core.music` (text-to-music) via `abstractmusic`

This split keeps `abstractcore` lightweight by default.

## Library mode (Python)

### Install

```bash
pip install abstractcore
pip install abstractvoice      # enables core.voice + core.audio
pip install abstractvision     # enables core.vision
pip install abstractmusic      # enables core.music
```

### Discover what's available

```python
from abstractcore import create_llm

llm = create_llm("ollama", model="qwen3:4b-instruct")  # example; pick a provider/model you have access to
print(llm.capabilities.status())
```

Notes:
- Capabilities load lazily the first time you access `llm.capabilities` / `llm.voice` / `llm.audio` / `llm.vision` / `llm.music`.
- Missing plugins raise an actionable error (includes an install hint).

### Use voice/audio (STT/TTS)

```python
wav_bytes = llm.voice.tts("Hello from AbstractVoice", format="wav")
open("hello.wav", "wb").write(wav_bytes)

text = llm.audio.transcribe("speech.wav")
print(text)
```

### Use generative vision (T2I/I2I/...)

`core.vision` can use an OpenAI-compatible images backend (configured via `vision_base_url` / `ABSTRACTVISION_BASE_URL`).

```python
llm = create_llm(
    "openai",
    model="gpt-4o-mini",
    vision_base_url="http://localhost:8000/v1",  # any OpenAI-compatible images endpoint
)

png_bytes = llm.vision.t2i("a red square on white background")
open("out.png", "wb").write(png_bytes)
```

### Use music generation (T2M)

`core.music` is plugin-backed (like voice/vision). `abstractmusic` provides
**local in-process** generation, with **ACE-Step Official**
(`acestep-official`) as the recommended backend and Diffusers audio pipelines
as alternative backends.

```python
llm = create_llm(
    # Any provider/model works here. The LLM does *not* generate music audio.
    # Music generation is performed by the configured AbstractMusic backend.
    "ollama",
    model="qwen3:4b-instruct",
    music_backend="acestep-official",
    music_model_id="ACE-Step/Ace-Step1.5",
)

wav_bytes = llm.music.t2m("uplifting synthwave, 120bpm, catchy chorus", format="wav", duration_s=10.0)
open("out.wav", "wb").write(wav_bytes)
```

## Framework mode (gateway/runtime)

Install modality plugins on the durable host (the machine/process that runs the runtime + tool execution and imports
`abstractcore`), typically the AbstractGateway runner.

Thin clients (web, remote TUI) do not need `abstractvoice`/`abstractvision`/`abstractmusic` installed locally.

## Server mode (OpenAI-compatible `/v1`)

AbstractCore Server can optionally expose OpenAI-compatible endpoints by delegating to plugins:
- `/v1/images/*` (via `abstractvision`)
- `/v1/audio/*` (via the capability plugin layer, typically `abstractvoice`; plus `/v1/audio/music` when `abstractmusic` is installed)

These endpoints are interoperability-first. For durable artifact-backed outputs, prefer gateway/runtime + ArtifactStore.

--- docs/guide/deployment-topologies.md ---
# Deployment Topologies (Supported Patterns)

AbstractFramework is easier to reason about if you think in roles, not packages:

- UI / host UX: renders progress, collects approvals (AbstractCode, browser UIs, custom apps)
- Orchestrator: durable state machine + stores (AbstractRuntime + stores)
- Agent logic: produces effects/steps (AbstractAgent patterns, flows)
- LLM gateway: provider abstraction + tool-call parsing (AbstractCore)
- Tool executors: side effects (local tools, MCP workers, sandboxes)

## Topology A: Single machine (local everything)

Best for local development and offline-first workflows.

- UI + runtime + tools run in one process (or one machine).
- You can still use file-backed stores for durability.

## Topology B: Local orchestration + remote inference

Best when you want local tool execution but a remote model (GPU box, cloud API, hosted vLLM).

- Runtime + tools stay local.
- AbstractCore routes LLM calls to a remote provider endpoint.

## Topology C: Remote tool execution (MCP-backed)

Best when tools must run near the target environment (servers, private networks, sandboxes).

- Runtime stays on the durable host.
- Tool calls are delegated to an MCP worker.

## Topology D: Thin client UI + remote durable host (Gateway-first)

Recommended for multi-device use and trusted multi-client use.

- The gateway host owns the durable runtime + stores and progresses runs.
- Thin clients render by replaying/streaming the ledger and act by submitting durable commands.
- Bundles (`.flow`) provide portable, discoverable specialized agents.
- A single Gateway bearer token is not a tenant/user isolation boundary. For
  independent users, route each user or tenant to a separate Gateway/runtime/data
  plane until tenant-aware Gateway authorization exists.

## Topology E: Multi-host orchestration (planned/advanced)

Only needed when you want to distribute durable orchestration itself across multiple hosts.
For v0, prefer picking a host per run (avoid mid-run migration).

## See also

- [Scenario: Gateway-first local development](../scenarios/gateway-first-local-dev.md)
- [Guide: Gateway exposure security](gateway-security.md)

--- docs/guide/deployment-web.md ---
# Web Deployment (Browser UI + Gateway)

This guide covers deploying a browser UI (Observer / Flow Editor / Code Web UI) against an AbstractGateway.

## What "gateway-first" means

- The browser does not tick the runtime.
- It renders by replaying/streaming the ledger.
- It acts by sending durable commands (start/resume/pause/cancel/emit_event).

## Minimum gateway settings (browser access)

Set these on the gateway host:

```bash
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export ABSTRACTGATEWAY_USER_AUTH=1
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
```

Start the gateway:

```bash
abstractgateway serve --host 127.0.0.1 --port 8080
```

## Run the UIs

```bash
npx @abstractframework/observer
npx @abstractframework/flow
npx @abstractframework/code
```

Default ports:
- Observer: http://localhost:3001
- Code Web UI: http://localhost:3002
- Flow Editor: http://localhost:3003

In each UI, set:
- Gateway URL: `http://127.0.0.1:8080`
- User: the Gateway user id assigned by the Gateway admin
- Gateway token: that user's token, used only to create the browser session

For hosted deployments on a non-local UI hostname, configure the Gateway URL on
the UI server. Browser-supplied Gateway URL changes are rejected by Flow, Code
Web, and Observer unless the app-specific
`*_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG=1` override is enabled behind your own
access control. If the UI is behind a reverse proxy that rewrites `Host`, enable
`*_TRUST_PROXY_HEADERS=1` only after the proxy strips client-supplied forwarded
headers.

## Production notes (high-signal)

- Terminate TLS at a reverse proxy and forward to `127.0.0.1:8080`.
- Restrict `ABSTRACTGATEWAY_ALLOWED_ORIGINS` to exact UI origins (avoid broad wildcards).
- Keep the Gateway admin token secret and rotate it like any control-plane
  credential.
- Hosted browser apps should keep only their app-scoped Gateway session cookie;
  do not persist user bearer tokens in browser storage.
- Do not use one shared user token for independent users. Use Gateway
  per-principal routing so each user token maps to that user's runtime.

See [Guide: Gateway exposure security](gateway-security.md).

--- docs/guide/deployment-iphone.md ---
# iPhone Notes (Safari / PWA)

Code Web UI is designed to run on iPhone as a thin host UI that connects to a remote gateway deployment.

## Prereqs (recommended)

- Gateway reachable over HTTPS (reverse proxy + TLS).
- Web UI hosted over HTTPS.
- Gateway configured with:
  - `ABSTRACTGATEWAY_AUTH_TOKEN` (recommended)
  - `ABSTRACTGATEWAY_ALLOWED_ORIGINS` including your web UI origin (exact host recommended for prod)

## Steps

1. Open the web UI URL in Safari.
2. In Settings:
   - set Gateway URL (for example `https://gateway.example.com`)
   - set auth token if required
3. Optional: Safari -> Share -> Add to Home Screen.

## Constraints

- iOS suspends background tabs aggressively; durability depends on ledger replay, not "staying connected".
- File access is remote (via gateway); the phone does not run local tools in v1.


--- docs/guide/gateway-security.md ---
# Gateway Exposure Security (Checklist)

Treat `abstractgateway serve` as a control-plane service: it can access runs/ledgers/attachments, and (optionally) execute
maintenance actions depending on your deployment.

## Recommended defaults (local dev)

- Bind to loopback: `--host 127.0.0.1`
- Use a strong token:

```bash
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
```

- Enable Gateway user auth when browser apps need per-user runtime routing:

```bash
export ABSTRACTGATEWAY_USER_AUTH=1
```

- Allow only localhost origins for browser UIs:

```bash
export ABSTRACTGATEWAY_ALLOWED_ORIGINS="http://localhost:*,http://127.0.0.1:*"
```

## If exposing beyond localhost (LAN, tunnels, internet)

1. Run behind TLS (reverse proxy or a trusted tunnel).
2. Use a strong token and rotate it periodically.
3. Restrict `ABSTRACTGATEWAY_ALLOWED_ORIGINS` to exact UI origins (avoid broad wildcards).
4. Protect reads as well as writes (ledgers contain prompts and tool outputs).

## User isolation

When Gateway user auth is enabled, each user token resolves to a Gateway
principal and runtime mapping. Hosted browser apps such as AbstractFlow,
AbstractCode Web, and AbstractObserver exchange the signed-in user's token for
a Gateway browser session, store only an app-scoped opaque session id in an
HTTP-only browser cookie, and forward that session to Gateway server-side. The
raw user token is not stored in browser settings, and Gateway login response
bodies do not expose the session id or CSRF token. Mutating proxied Gateway
requests also carry a CSRF token. A server/admin token does not sign in
browsers. Gateway browser session cookies use an HTTP-only cookie for the
session id, a separate CSRF cookie, `SameSite=Lax`, path `/`, no `Secure` flag
on plain HTTP, and `Secure` when served over HTTPS. Sessions expire, logout
revokes the session record, and disabling/deleting/rotating the backing Gateway
user invalidates existing sessions.

For independent users, prefer `1 user = 1 runtime` through Gateway's
per-principal router. Gateway rejects duplicate runtime ids within the same
tenant when creating or updating users, so an admin cannot accidentally map two
tenant users to the same runtime. When a user is deleted, Gateway removes that
user's credential but reserves the retained runtime id for that deleted
principal; assigning the retained runtime to a different user is rejected unless
an admin explicitly transfers or purges the retained runtime reservation. Purge
requires exact runtime-id confirmation and deletes the retained runtime directory
before releasing the runtime id. Transfer assigns the retained runtime to an
existing same-tenant user and reserves that user's previous runtime id. Keep
shared/cross-user memory or collaboration explicit, permissioned, and auditable.

Hosted browser apps use the server-configured Gateway URL on non-local hosts.
AbstractFlow, AbstractCode Web, and AbstractObserver reject browser-supplied
Gateway URL changes when the UI is served from a non-loopback hostname. Enable
the app-specific override only behind your own access control:
`ABSTRACTFLOW_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG=1`,
`ABSTRACTCODE_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG=1`, or
`ABSTRACTOBSERVER_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG=1`. The host check uses
the request `Host` header by default. Trust proxy headers only when your reverse
proxy strips client-supplied forwarded headers, using the app-specific
`*_TRUST_PROXY_HEADERS=1` setting or `ABSTRACTGATEWAY_TRUST_PROXY_HEADERS=1`.

Shared workflows are handled through the Gateway workflow catalog rather than
by sharing a user's private runtime bundle directory. Catalog versions are
immutable by `bundle_id@version`; admins can move a default pointer, set ACLs,
deprecate or block a version, or tombstone it without deleting the stored
bundle bytes. Catalog workflows run in the requesting user's runtime by
default, so the shared workflow definition does not imply shared run state.
Run-start policy checks the signed-in user's tenant, roles, and catalog ACL
before execution. Private `/api/gateway/bundles` routes remain per-runtime
authoring surfaces.

Catalog bundles are loaded under internal host ids, but those internal ids are
not a public authorization surface. Direct private-bundle inspection routes
reject catalog-internal ids; use the ACL-aware `/api/gateway/workflow-catalog`
routes to list or inspect shared workflows. Gateway also strips client-supplied
`_runtime.workflow_policy` values and replaces catalog starts with a signed
Gateway-issued policy snapshot before Runtime sees the run.

Gateway serves a built-in admin/account console at `/console`. The console uses
the same browser-session contract: users sign in with a Gateway user id and
token, then the browser keeps only the opaque session cookie. Because the
console is served by Gateway itself, it does not ask for a Gateway URL; the
current origin is the Gateway. Admin users can
manage Gateway users, rotate tokens, and handle retained runtime reservations
from this console. Signed-in users can set their own capability defaults from
Gateway-discovered provider/model catalogs. Admin/root defaults act as the
Gateway baseline; normal users inherit that baseline and can override it only
for their own runtime.

The console also supports Gateway-owned provider endpoint profiles. Profiles
can describe OpenAI-compatible or hosted provider endpoints with a display name,
description, provider family, base URL, API key, capabilities, and optional
model allowlist. Discovery exposes only non-secret metadata and a virtual
provider id such as `endpoint:office-vllm`; Gateway injects the raw key only into
the runtime call that resolves that profile. Normal users can create user-scoped
profiles. Gateway-scoped profiles require an admin principal.

Gateway keeps operator surfaces admin-only through a central route-family
policy. User management, audit/process/backlog/triage/report routes, email
bridge routes, host metrics, model residency list/load/unload, server workspace
file helpers, and server workspace artifact import/export require an admin
principal. Browser local files should use upload routes; server filesystem
read/import/export is not exposed to ordinary hosted users.

Discovery metadata is permission-aware for these high-trust surfaces. Ordinary
users see admin-only workspace artifact import/export and provider prompt-cache
control operations marked unavailable with `admin_required` metadata. Their
session prompt-cache names are still usable, but the private hash includes the
current principal scope so two users cannot collide by choosing the same
session id, provider, and model.

## Verify quickly

- `/api/health` returns `200`
- `/api/gateway/*` endpoints return `401` without `Authorization: Bearer ...`
- `/console` loads the Gateway Console, and admin-only actions return `403` for
  non-admin users

## See also

AbstractGateway has a deeper security guide (env vars, limits, lockouts, audit log):
- https://github.com/lpalbou/abstractgateway/blob/main/docs/security.md

--- docs/guide/capability-routing-defaults.md ---
# Capability Routing Defaults

Capability routing defaults define which provider/model/backend the framework should use when a
request does not provide an explicit route.

They are configuration, not residency. A route can be configured even when the provider does not
currently have that model loaded. Loaded-model state is reported separately by provider residency
endpoints and the AbstractFlow "Loaded models" view.

## Route Keys

Routes use:

```text
<kind>.<modality>
```

Route kinds:

- `input`: understanding or enrichment of request content.
- `output`: generation targets.
- `embedding`: vectorization for retrieval and indexes.
- `rerank`: ranking routes for a future reranker manager.

Core modalities:

- `text`
- `image`
- `video`
- `voice`
- `sound`
- `scene3d`

Examples:

- `input.text`: model used to understand text input.
- `input.image`: VLM or captioning route for images.
- `output.text`: model used for text generation.
- `output.image`: image generation backend.
- `output.voice`: TTS route.
- `embedding.text`: text embedding model for semantic retrieval.
- `rerank.text`: reserved route for text reranking.

## Route Payload

Each route stores a small JSON-safe target:

```json
{
  "provider": "lmstudio",
  "model": "qwen/qwen3.6-35b-a3b",
  "base_url": "http://127.0.0.1:1234/v1",
  "options": {
    "voice": "M1"
  }
}
```

`provider`, `model`, and `base_url` are shared fields. `options` is provider/plugin-specific and can
carry values such as a voice, language, quality preset, or backend profile.

Secrets do not belong in route defaults. API keys remain provider credentials managed by
AbstractCore, Gateway deployment secrets, or the capability plugin.

## Configuration Ownership

AbstractCore owns the schema and persistence. Routes live in:

```text
~/.abstractcore/config/abstractcore.json
```

Gateway is the control plane:

- co-located Gateway reads/writes the local AbstractCore config;
- split Gateway proxies to the configured AbstractCore server;
- Gateway does not create a separate provider/model defaults file.

In split deployments, `base_url` is interpreted from the execution host that actually calls the
provider. A URL that works from the Core/Runtime host may not work from the browser or Gateway host.

## Configure From Core

Set the framework text default:

```bash
abstractcore --set-global-default lmstudio:qwen/qwen3.6-35b-a3b
```

This writes explicit `input.text` and `output.text` route defaults while older config fields still
exist for compatibility with lower-level code.

Set one route directly:

```bash
abstractcore --set-capability-default output.voice \
  --capability-provider supertonic \
  --capability-model supertonic-3 \
  --capability-base-url http://127.0.0.1:5000/v1 \
  --capability-option voice=M1
```

Configure text embeddings:

```bash
abstractcore --set-capability-default embedding.text \
  --capability-provider lmstudio \
  --capability-model text-embedding-nomic-embed-text-v1.5 \
  --capability-base-url http://127.0.0.1:1234/v1
```

or through the embedding convenience commands:

```bash
abstractcore --set-embeddings-provider lmstudio
abstractcore --set-embeddings-model lmstudio:text-embedding-nomic-embed-text-v1.5
abstractcore --set-embeddings-base-url http://127.0.0.1:1234/v1
```

## Configure Through Gateway

Use Gateway when it is the operator/control-plane entry point:

```bash
abstractgateway-config defaults

abstractgateway-config set-default output.text \
  --provider lmstudio \
  --model qwen/qwen3.6-35b-a3b \
  --base-url http://127.0.0.1:1234/v1

abstractgateway-config set-default embedding.text \
  --provider lmstudio \
  --model text-embedding-nomic-embed-text-v1.5 \
  --base-url http://127.0.0.1:1234/v1
```

Gateway still has deployment settings such as host, port, auth, store backend, and the Core server
URL/token it uses to reach the execution host. Those are Gateway internals, not framework model
defaults.

## AbstractFlow UI

The AbstractFlow model residency modal separates:

- **Loaded models**: provider-reported runtime residency.
- **Defaults**: execution-host route defaults for input/output/embedding/rerank.

Changing a default route does not load a model. Loading/unloading is an operator action against the
provider/runtime residency surface.

## Related

- ADR: `docs/adr/0035-capability-routing-defaults.md`
- Gateway configuration: `abstractgateway/docs/configuration.md`
- Core configuration: `abstractcore/docs/centralized-config.md`

--- docs/guide/runtime-scope.md ---
# Runtime Scope (run / session / global / all)

This guide defines the meaning of **scope** across AbstractRuntime's memory effects and host UX.

## Why scope exists

The runtime stores durable "memory" under a runtime-owned namespace in run state. A scope decides **which durable owner**
receives reads/writes, and therefore which runs share memory.

## Scopes

### `run`

- The current `run_id`.
- Best for per-run working memory (notes/tags/compaction spans that should not leak outside this run).

### `session`

- Shared across runs that share the same `session_id`.
- Use when you want continuity across multiple runs launched by the same client "session".

Important: `session` is a host contract. If a host does not provide a stable `session_id`, session scope may degrade to
"per-run" behavior.

### `global`

- A single global owner shared across the whole runtime instance.
- Use for durable cross-session memory (preferences, stable facts).

### `all`

`all` is a query fan-out scope used by some operations to search across:
- `run`
- `session`
- `global`

This is why `global != all`:
- `global` means "only the global owner"
- `all` means "run + session + global"

## Practical examples

- "Remember this for the rest of this run": `scope=run`
- "Remember this for this user session": `scope=session`
- "Remember this forever": `scope=global`
- "Search everything I know": `scope=all`

## What survives a backend restart?

Scope controls *which durable owner* receives reads/writes, but persistence depends on the host stores:

- With file-backed stores (run store + ledger store + artifact store), `run`/`session`/`global` scoped memory persists.
- With in-memory stores, scope still works, but everything is lost on restart.

## Gateway API note (important)

If you start runs via the gateway and you want `scope=session` behavior across multiple runs, you must send a stable
`session_id` when starting those runs.


--- docs/guide/flow-and-kg-memory.md ---
# Flow + KG Memory (Memory object v0) - Guide

This guide explains how to configure KG memory recall + writeback in VisualFlow using the first-class `memory` object.

It is written for novice users of AbstractFlow and focuses on practical, step-by-step setup.

## What is the `memory` object?

`memory` is a JSON-safe object that groups "what memory the model can use" and "how KG memory is queried/written" into a
single value.

It is designed to:
- keep Agent / LLM Call nodes clean (one pin instead of many),
- be portable (host can pass one object),
- stay backward compatible (legacy per-pin keys still work).

Where it's used:
- Agent node: connect `memory` -> `agent.memory`
- LLM Call node: connect `memory` -> `llm_call.memory`
- RunnableFlow start (optional): `On Flow Start.memory` can be supplied by the client/run modal

## Quick start (recommended): use the Memory literal node

1. In AbstractFlow, add a **Memory** node (Literals -> Memory).
2. Edit its JSON to your desired configuration.
3. Connect:
   - `Memory.value` -> `Agent.memory` (or `LLM Call.memory`)
4. Run the flow and inspect the node trace:
   - When `use_kg_memory=true`, the model should receive a bounded "KG ACTIVE MEMORY" system block when recall finds
     relevant items.

## Provide memory from the client (RunnableFlow)

RunnableFlow workflows (interface `abstractcode.agent.v1`) can accept a `memory` input at start:

1. Ensure your `On Flow Start` node exposes an output pin `memory` (type `memory`).
2. Wire `On Flow Start.memory` into your Agent/LLM Call.
3. In your client (run modal / API), set `memory` as JSON.

### Best practice: defaults + overrides

If you want the flow to have good defaults but still allow overrides from the client:

1. Create a Memory (defaults) literal node (typed `memory`).
2. Ensure `On Flow Start` provides `memory = {}` by default.
3. Merge defaults + overrides and use that output as the effective memory object.

## Memory object schema (v0)

All keys are optional. Omitted keys mean "no override" (runtime defaults apply).

### Recall/source controls (Agent + LLM Call)

- `use_session_attachments: boolean`
- `use_span_memory: boolean`
- `use_semantic_search: boolean` (reserved; not implemented in v0)
- `use_kg_memory: boolean`
- `memory_query: string` (defaults to the node prompt/task if omitted)
- `memory_scope: string` (`run | session | global | all`)
- `recall_level: string` (`urgent | standard | deep`)
- `max_span_messages: number`
- `kg_max_input_tokens: number`
- `kg_limit: number`
- `kg_min_score: number` (0..1)

### KG write defaults (useful for ingest subflows)

- `kg_write_scope: string` (`run | session | global`)
- `kg_domain_focus: string`
- `kg_max_out_tokens: number` (0 means "no cap")

## Example memory object

```json
{
  "use_session_attachments": true,
  "use_span_memory": false,
  "use_semantic_search": false,
  "use_kg_memory": true,
  "memory_query": "",
  "memory_scope": "session",
  "recall_level": "standard",
  "max_span_messages": 24,
  "kg_max_input_tokens": 1200,
  "kg_limit": 80,
  "kg_min_score": 0.35,
  "kg_write_scope": "session",
  "kg_domain_focus": "software / agents / memory systems",
  "kg_max_out_tokens": 0
}
```

## Query and insert (KG recall + KG writeback)

### Query (recall)

To make an Agent/LLM Call use KG recall:
1. Set `memory.use_kg_memory = true`.
2. Optionally set `memory.memory_query` (otherwise the prompt is used).
3. Choose `memory.memory_scope`:
   - `session` is common when you want continuity within one client session.
   - `global` is common when you want durability across independent runs.

### Insert (writeback)

To write new knowledge into the KG, run an ingestion step/subflow after you produce an answer.
The typical pattern is to build a turn transcript string and pass it to an extractor that writes assertions using:
- scope from `memory.kg_write_scope` (or a fixed literal)
- domain hint from `memory.kg_domain_focus`


--- docs/guide/scheduled-workflows.md ---
# Scheduled Workflows (Durable Jobs)

This guide explains how scheduled workflows work when using `abstractgateway` + `abstractruntime`.

## What "scheduled workflows" means in AbstractFramework

A scheduled workflow is a durable parent run that triggers a target workflow as child runs over time.

Key properties:
- Durable: schedule state is persisted and survives restarts.
- Replay-first observability: you can attach later and reconstruct what happened from the ledger.
- Single authority: the gateway host owns ticking/resuming.

## Who "runs" the schedule (and why it stops when processes stop)

AbstractRuntime is a library. It can represent "wait until time X", but it does not create OS timers or wake itself up.

Something must keep calling `Runtime.tick(...)` to advance runs. In the gateway topology, the gateway runner loop:
- ticks running runs
- resumes due waits (including "wait until" for scheduled jobs)
- applies durable commands (pause/resume/cancel/emit_event)

If you stop the gateway process, nothing ticks. When it restarts, due waits resume on the next poll cycle.

## Creating a scheduled run (Gateway HTTP API)

Endpoint: `POST /api/gateway/runs/schedule`

Example: start now, repeat every 20 minutes forever:

```bash
curl -sS -X POST "http://127.0.0.1:8080/api/gateway/runs/schedule" \
  -H "Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_id": "my-bundle",
    "flow_id": "root",
    "input_data": { "prompt": "write my report" },
    "start_at": "now",
    "interval": "20m",
    "share_context": true
  }'
```

Example: start at a specific time (UTC ISO), run 10 times:

```bash
curl -sS -X POST "http://127.0.0.1:8080/api/gateway/runs/schedule" \
  -H "Authorization: Bearer $ABSTRACTGATEWAY_AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bundle_id": "my-bundle",
    "flow_id": "root",
    "input_data": { "prompt": "write my report" },
    "start_at": "2026-01-15T15:06:00+00:00",
    "interval": "20m",
    "repeat_count": 10
  }'
```

Notes:
- Intervals are relative (drift is expected if runs take time or the gateway is down).
- If a child run blocks on a durable wait (ask-user, approvals, wait-event), the schedule blocks too (it waits for the
  child to finish).
- Durable execution is not transactional I/O (at-least-once semantics). Prefer idempotent outputs for scheduled jobs.

## Controlling scheduled runs

Scheduled runs are normal durable runs:
- Pause the parent run to pause the schedule.
- Cancel the parent run to stop the schedule and cancel active children.

This is done via `POST /api/gateway/commands`.


--- docs/guide/prompt-caching.md ---
# Prompt Caching (Prompt / KV)

This guide explains how the framework should think about caching for LLM calls, with an emphasis on prompt/KV caching
(prefill reuse) rather than response memoization.

## Terminology (three different "caches")

1. Response cache (exact/semantic)
   - Memoize final model outputs keyed by the input request.
   - Useful for repetitive questions, but risky for correctness drift.

2. Prompt/KV cache (prefix/prefill reuse)
   - Reuse the model's internal KV state for repeated prompt prefixes.
   - This can dramatically reduce time-to-first-token for long prompts with stable prefixes.

3. Composable KV modules (advanced)
   - Precompute caches for separate chunks (docs, history) and stitch them later.
   - This is typically an engine-level feature and not guaranteed uniformly across providers.

## AbstractCore support (best-effort)

AbstractCore exposes a provider-optional prompt cache surface. Depending on provider/backend, it may be:
- fully supported (in-process local backends),
- pass-through to an upstream server,
- or a no-op.

Typical usage patterns:

```python
from abstractcore import create_llm

llm = create_llm("mlx", model="mlx-community/Qwen3-4B")
llm.prompt_cache_set("tenantA:session123")  # also sets the default key

llm.generate("Hello")
llm.generate("Continue, but shorter.")
```

Or per-call:

```python
resp = llm.generate("Summarize this.", prompt_cache_key="tenantA:session123")
```

## Gateway/runtime note

In gateway-first deployments, prompt caching (when enabled) should be scoped per user/session to avoid accidental
cross-user reuse. Prefer stable `session_id` values so cache keys remain stable across multiple runs.


--- docs/guide/workflow-bundles.md ---
# WorkflowBundles (`.flow`) and Lifecycle

WorkflowBundles (`.flow`) are the portable distribution unit for VisualFlow workflows:

- a zip bundle containing `manifest.json` + `flows/*.json` (and optional assets)
- entrypoints can advertise interface contracts (for example `abstractcode.agent.v1`) for discovery across clients

## Where bundles live (gateway-first)

On a gateway host, configure a bundles directory:

```bash
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/workflows"   # contains *.flow
```

The gateway discovers and serves bundles to thin clients via discovery endpoints.

Hosted gateways now distinguish two bundle registries:

- **Private runtime bundles** live in the caller's routed runtime and are served
  through `/api/gateway/bundles`. AbstractFlow's normal save/publish/test loop
  continues to use this private surface.
- **Workflow catalog bundles** live in the Gateway control plane and are served
  through `/api/gateway/workflow-catalog`. Admins upload or promote immutable
  `.flow` versions, move explicit default pointers, set ACLs, and deprecate,
  block, or tombstone versions without deleting bundle bytes.

Catalog workflows run in the requesting user's runtime by default. Clients
start them with `registry_scope: "tenant_catalog"` plus `bundle_id`,
`bundle_version` when an exact version is required, and `flow_id`. If the
version is omitted, Gateway resolves the admin-managed default pointer rather
than guessing from semantic version order. Exact older versions keep working
until that specific version is deprecated, blocked, or tombstoned.

Catalog starts must be explicit. If `registry_scope` is omitted, Gateway treats
the request as a private-runtime bundle start and will not silently fall through
to the shared catalog. Catalog run policy is Gateway-issued and signed before it
is passed into Runtime state; clients cannot authorize catalog subworkflow
starts by sending their own `_runtime.workflow_policy`.

## Recommended lifecycle controls

- Publish/install new versions instead of editing deployed bundles in place.
- Deprecate workflows instead of deleting:
  - hides from discovery
  - blocks new starts
  - keeps old versions available for replay/audit of historical runs
- For shared/default workflows, use the workflow catalog. Do not overwrite
  catalog bundle bytes for an existing `bundle_id@version`; publish a new
  immutable version and move the default pointer.
- `framework_catalog` is reserved for a later cross-tenant catalog. The
  implemented shared catalog scope today is `tenant_catalog`.

## See also

- [Scenario: Publish, install, and deprecate workflows](../scenarios/workflow-bundle-lifecycle.md)

--- docs/guide/agent-skills.md ---
# Agent Skills (SKILL.md) — Proposal

This guide captures a **planned** integration of the Agent Skills (`SKILL.md`) format into AbstractFramework.
Nothing in this document implies the feature is already shipped; it records a design direction so the knowledge
is not lost.

## What are “Agent Skills”?

In the Agent Skills ecosystem, a **skill** is a shareable folder with a required `SKILL.md` (YAML frontmatter +
instructions) plus optional `scripts/`, `references/`, and `assets/`. Skills are designed for **progressive disclosure**:
systems load only `name`/`description` for discovery and fetch the full content only when a skill is activated.

Spec constraints worth carrying into AbstractFramework:
- `name` is constrained (lowercase alphanumeric + hyphens, 1–64 chars) and must match the skill’s leaf directory name.
- `allowed-tools` is **experimental** and is a space-delimited list of “pre-approved” tools in the originating ecosystem.

## Skills vs flows (what each is “for”)

- **Flows** (`.flow` bundles / VisualFlow) are **executable programs** in AbstractFramework:
  durable execution, explicit waits, tool boundaries, replayable ledger history.
- **Skills** (`SKILL.md`) are **portable procedure packs**:
  prompt/instructions + optional scripts/resources, designed to be shared across agents/ecosystems.

### Are flows “more advanced” than skills?

They’re “more advanced” in different dimensions:

- **Execution**: flows are more advanced (they *run* as durable state machines).
- **Portability**: skills are more advanced (they’re a widely adopted, tool-agnostic packaging standard).

### Can every skill be modeled as a flow?

**Conceptually yes**: a skill is “a procedure + resources”, and a flow can orchestrate any procedure.
In practice, the limit is **tooling/environment assumptions**, not the flow model:
a skill may assume Playwright is installed, or a specific “container” tool surface exists.

Also, not every skill is *worth* turning into a dedicated flow:
“guidelines/checklists/style” skills often work best as **prompt modules** attached to a generic agent flow.

## Proposed interaction model (v0)

The key design choice is: **flows run; skills are activated/loaded** (and skill scripts only run as explicit tools).

### 1) Run-attached skills (primary)

- Clients/hosts attach an `available_skills` metadata set to a run (name/description only).
- Users explicitly activate a skill (e.g. `/skill <name>`), which loads full `SKILL.md` and any resources.
- Activation is logged durably (ledger record). For replay/resume safety, activation should snapshot skill content
  (or at least record a content hash) so a long-running run doesn’t silently pick up a modified skill file.

### 2) Bundle-declared skill dependencies (secondary)

Flows may declare skill dependencies without changing the `.flow` format by using `manifest.metadata`, for example:

- `skills.required`: skills that must be present on the host/gateway
- `skills.defaults`: skills to auto-activate at run start

This lets organizations ship a workflow that says “this workflow expects these skills”, while keeping skills
as separately managed artifacts.

### 3) Bundle-embedded skills (optional; later)

WorkflowBundles support `assets/*`. If we want hermetic distribution (“workflow + skills in one file”),
we can embed skills under bundle assets (e.g. `assets/skills/<id>/...`) and expose them via the gateway.

## Implementation notes (what fits best with existing runtime/flow mechanics)

The lowest-friction implementation in AbstractFramework is to add skills as **runtime-owned tools** in the
AbstractRuntime ↔ AbstractCore integration (the same pattern already used for `open_attachment`):

- `list_skills()` for metadata-only discovery (progressive disclosure).
- `open_skill(...)` to load full `SKILL.md` (and optionally specific resources), snapshotting large payloads as artifacts
  and recording a content hash.
- optional `activate_skill(...)` to update durable run state (`_runtime.skills.active`) and apply `allowed-tools` as a
  restriction (intersection with the run’s tool allowlist).

Because these are tools, **flows can compose over skills immediately** using existing Tool/CallTool nodes, and agent
loops can activate skills without introducing new effect types.

Note: bundle-declared dependencies via `manifest.metadata.skills.*` are supported as a pattern, but VisualFlow JSON
currently has no `metadata` field; making this authorable requires a UI/CLI surface (or a schema extension).

## Safety and tool gating

- Skills may include scripts. **Scripts must never run implicitly** “because a skill exists”.
- Skills may declare `allowed-tools` (ecosystem field; experimental). In AbstractFramework the safe behavior is:
  - treat it as a **restriction** when it can be mapped to AbstractFramework tool names (intersection with the run’s tool allowlist),
  - if it cannot be mapped (unknown grammar/tool ids), emit `#FALLBACK` and **do not relax** the run’s tool policy,
  - deny and log out-of-policy tool calls with actionable `#FALLBACK` warnings,
  - keep run state JSON-safe (store bodies/resources as artifacts when large).

## Where this fits (packages)

- `abstractagent`: prompt injection of metadata; “activate skill” as an explicit step; optional schema-only built-in
  (e.g. `open_skill`) so the runtime/host performs the read.
- `abstractruntime`: runtime-owned “skill read/activate” handler that is durable + ledger-recorded + artifact-backed,
  plus enforcement hooks for `allowed-tools`.
- `abstractgateway`: optional “skills registry” (list/fetch/install/deprecate), parallel to `.flow` bundle distribution.
- `abstractcore`: stays lean; any provider-specific “container skills” integration remains optional and gated.

## References and next steps

- Backlog item: `docs/backlog/planned/074_agent_skills_integration.md`
- Implementation plan (phased): `docs/backlog/planned/074_agent_skills_integration_plan.md`
- Research notes (spec + ecosystem scan): `docs/skills/`

--- docs/guide/telegram-integration.md ---
# Telegram Integration (Gateway Bridge + Workflow)

This guide explains how to run a Telegram "permanent contact" that talks to an agent workflow through the gateway.

Telegram is implemented as a **thin client**:
- Inbound Telegram messages -> gateway starts a new run per message (stable `session_id` for durable memory)
- Outbound replies -> the bridge sends the run output back to Telegram
- Attachments -> stored in the ArtifactStore and passed as `context.attachments` / `context.media`

## Security model choices

Telegram has two integration paths:

1. TDLib + Secret Chats (E2EE in transit; recommended)
2. Bot API (easy, not E2EE)

Even with E2EE, messages are decrypted on the gateway host and persisted to durable stores in plaintext by design. Secure
the gateway host and its storage.

## Access control (critical)

Telegram bots and user accounts are discoverable. Without access control, anyone who finds the handle can message it and
trigger durable runs + LLM calls.

The bridge is **fail-closed by default**:
- DMs: `ABSTRACT_TELEGRAM_DM_POLICY=allowlist` (default) — only allowlisted Telegram `user_id`s are processed.
- Groups: `ABSTRACT_TELEGRAM_GROUP_POLICY=disabled` (default) — all group/supergroup/channel messages are ignored.
- Unauthorized messages are ignored (no run created, no token spend). `/whoami` always works.

Commands:
- `/whoami` — always works; prints your `user_id` and `chat_id` (useful for allowlists).
- `/pair ...` — pairing workflow (DM only; only when `ABSTRACT_TELEGRAM_DM_POLICY=pairing`).

Minimal env vars (Bot API + DM allowlist):

```bash
export ABSTRACT_TELEGRAM_BRIDGE=1

# Bot API (easy, not E2EE). If ABSTRACT_TELEGRAM_BOT_TOKEN is set, transport defaults to bot_api.
export ABSTRACT_TELEGRAM_BOT_TOKEN="..."  # from @BotFather

# Allowlisted DM users (numeric Telegram user_id). Use /whoami to discover yours.
# Accepts comma/newline-separated ints or JSON list.
export ABSTRACT_TELEGRAM_ALLOWED_USERS="123456789"
```

## Quickstart (DM-only allowlist)

This is a practical checklist to verify access control + approvals end-to-end.

1. Configure the bridge (Bot API):

```bash
# Gateway (required for `abstractgateway serve`).
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/bundles"  # directory containing *.flow bundles (incl. shipped `basic-agent`)
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"

export ABSTRACT_TELEGRAM_BRIDGE=1
export ABSTRACT_TELEGRAM_BOT_TOKEN="..."               # from @BotFather
```

2. Start the gateway.
   - You may see a warning about an empty DM allowlist; this is expected until you set `ABSTRACT_TELEGRAM_ALLOWED_USERS`.
   - Then DM the bot and run `/whoami`.
   - Copy your `user_id` (the bot also prints an `export ABSTRACT_TELEGRAM_ALLOWED_USERS="..."` hint).

3. Set your allowlist and restart the gateway:

   - `export ABSTRACT_TELEGRAM_ALLOWED_USERS="123456789"`

4. Verify:
   - From an allowlisted account, send “hi” → expected: you receive a reply.
   - From a non-allowlisted account, send “hi” → expected: ignored (except `/whoami`).

5. Verify tool approvals:
   - In the chat, ask: `run free -m` (or `uname -a`).
   - Expected: the bot asks you to reply `/approve` before executing `execute_command`.
   - Expected: after `/approve`, you receive the final answer/result in Telegram (read-only tools like `web_search` should not require approval).

## Optional: pairing mode (DMs)

Pairing lets unknown users request access without editing `ABSTRACT_TELEGRAM_ALLOWED_USERS`, but it requires an admin.

```bash
export ABSTRACT_TELEGRAM_DM_POLICY="pairing"
export ABSTRACT_TELEGRAM_ADMIN_USERS="123456789"   # your operator user_id (use /whoami)
export ABSTRACT_TELEGRAM_PAIRING_TTL_S="3600"      # optional
```

## Optional: group chat support

Group chats are disabled by default. To enable allowlisted groups:

```bash
export ABSTRACT_TELEGRAM_GROUP_POLICY="allowlist"
export ABSTRACT_TELEGRAM_ALLOWED_CHATS="-100123456789"  # use /whoami inside the group to discover chat_id
# Optional (default true): require @mention in groups
export ABSTRACT_TELEGRAM_REQUIRE_MENTION_IN_GROUPS=1
```

## Viewing Telegram sessions in AbstractCode

Telegram runs are durable; you can replay them from any thin client.

1. Open AbstractCode (default): http://localhost:3002
2. Go to **History**, click **Refresh**, then open the Telegram session (e.g. `telegram:<chat_id>:r<rev>`).

Notes:
- Each incoming Telegram message creates a new run under the same `session_id` (durable memory across turns).

## Minimal gateway configuration

Install Telegram support:

```bash
pip install abstractgateway
# Optional (only if your workflows call Telegram tools like `send_telegram_message`):
# pip install "abstractcore[tools]"
```

Set env vars on the gateway host:

```bash
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/bundles"  # directory containing *.flow bundles
export ABSTRACTGATEWAY_AUTH_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"  # required

export ABSTRACT_TELEGRAM_BRIDGE=1

# Bot API (easy, not E2EE). If ABSTRACT_TELEGRAM_BOT_TOKEN is set, transport defaults to bot_api.
export ABSTRACT_TELEGRAM_BOT_TOKEN="..."
export ABSTRACT_TELEGRAM_ALLOWED_USERS="123456789"  # use /whoami

# Tool execution + approvals:
# - `approval` (default): safe tools run in-process; dangerous/unknown tools still require a Telegram reply: `/approve` or `/deny`.
# - `passthrough`: delegated execution (advanced; not recommended for thin clients).
export ABSTRACTGATEWAY_TOOL_MODE="approval"

# Optional: override which workflow to run per message.
# Default (when unset): shipped `basic-agent` bundle entrypoint.
# export ABSTRACT_TELEGRAM_BUNDLE_ID="basic-agent"
# export ABSTRACT_TELEGRAM_FLOW_ID="81795ea9"
```

Notes:
- Default LLM routing comes from the execution-host `output.text` capability route. Set it with
  `abstractcore --set-global-default ...` or `abstractgateway-config set-default output.text ...`.
- Telegram-only routing override (does not affect other gateway traffic): set `ABSTRACT_TELEGRAM_MODEL="..."` (and optionally `ABSTRACT_TELEGRAM_PROVIDER="..."`).
- Durable history limit: `ABSTRACT_TELEGRAM_MAX_HISTORY_MESSAGES` (default: 30; `0` keeps only system messages).
- STT fallback and vision caption fallback are configured via `abstractcore --config` (audio strategy + vision fallback).
- Telegram typing keepalive is best-effort: tune with `ABSTRACT_TELEGRAM_TYPING_INTERVAL_S` (default: 4s) and `ABSTRACT_TELEGRAM_TYPING_MAX_S` (default: 600s; set to `0` to disable).
- `/reset` behavior is best-effort: the bridge clears the durable session, sends a confirmation message, and optionally deletes recent messages in the background. Controls: `ABSTRACT_TELEGRAM_RESET_DELETE_MESSAGES` (default: true), `ABSTRACT_TELEGRAM_RESET_DELETE_MAX` (default: 200), `ABSTRACT_TELEGRAM_RESET_MESSAGE` (confirmation text). Telegram may still reject deletions depending on chat permissions and age.

Start the gateway normally.

## Local dev test (Bot API + LMStudio)

If you're in the AbstractFramework repo, you can use `./execute.sh` as a convenience env setup:

```bash
source ./execute.sh
```

1. Start LMStudio “Local Server” and load `google/gemma-3n-e4b`.
2. Set the text output route for this run:

```bash
abstractgateway-config set-default output.text \
  --provider lmstudio \
  --model google/gemma-3n-e4b \
  --base-url http://127.0.0.1:1234/v1
export LMSTUDIO_BASE_URL="http://127.0.0.1:1234/v1"
```

3. Ensure the gateway can see the shipped bundle (a directory containing `*.flow`):

```bash
export ABSTRACTGATEWAY_FLOWS_DIR="/path/to/bundles"  # e.g. ./abstractgateway/flows/bundles in this repo
```

4. Send a Telegram message to the bot and verify:
   - you receive a reply
   - a follow-up (“What did I just say?”) works (durable memory)
   - media messages (photo/voice/video/document) are handled

## Workflow wiring (VisualFlow)

### Default workflow (recommended)

By default, the bridge runs the shipped `basic-agent` bundle entrypoint once per incoming message and sends the run output back to Telegram.
Durable memory comes from the stable Telegram `session_id` (no special workflow shape required).

### Custom workflow

Any flow that reads `prompt`/`context` (like `abstractcode.agent.v1`) and writes a string to `run.output.answer` or `run.output.response` will work.
The bridge provides Telegram metadata in `input_data.telegram` if you want to branch on it.

## TDLib notes (E2EE path)

TDLib requires:
- a real Telegram user account for the AI identity
- the TDLib shared library (`tdjson`) installed on the gateway host
- a persistent TDLib session directory (so you authenticate once)

Because TDLib is platform-specific, keep your setup steps close to your deployment scripts. The gateway integration code
and configuration surface live in:
- https://github.com/lpalbou/abstractgateway

## Testing checklist

1. Confirm the gateway loaded your bundles (API: `GET /api/gateway/bundles`) and that the configured Telegram flow exists.
2. Send a message to the bot; verify you get a reply and that Observer can replay the run.
3. Send a follow-up (“What did I just say?”) to confirm durable memory works.
4. Send media:
   - photo (with and without caption)
   - voice note (STT fallback depends on your `abstractcore --config` audio strategy + installed plugins)
   - video and document
5. Send `/reset` to clear the binding/runs, then confirm the next message starts fresh.

## Tool approvals (Telegram)

When the agent requests a tool call that requires explicit permission (for example `write_file` or `execute_command`),
the bridge sends an approval prompt into the chat. Reply with:
- `/approve` (or `approve`) to execute the tool calls and continue
- anything else to cancel the tool calls and let the workflow continue with failure results
 
Note: `/tools` is intentionally disabled in thin-client mode; use `/approve` and `/deny`.

--- docs/guide/email-integration.md ---
# Email Integration (Inbound IMAP -> Events, Outbound SMTP Defaults)

This guide explains how to use framework-native email tooling:

- Outbound: `send_email` with centralized SMTP defaults (no repeated host/user per call)
- Inbound: gateway email bridge polls IMAP and emits durable `email.message` events into stable sessions, with
  artifact-backed attachments

## Minimal outbound configuration (SMTP defaults)

Configure on the process that executes tools (gateway local tools, CLI host, or tool worker):

```bash
export ABSTRACT_EMAIL_SMTP_HOST="smtp.example.com"
export ABSTRACT_EMAIL_SMTP_USERNAME="me@example.com"
export ABSTRACT_EMAIL_SMTP_PASSWORD_ENV_VAR="EMAIL_PASSWORD"
export EMAIL_PASSWORD="..."
```

Then a minimal tool call can be:

```json
{ "name": "send_email", "arguments": { "to": "you@example.com", "subject": "Hello", "body_text": "Hi!" } }
```

## Minimal inbound configuration (gateway email bridge)

Configure IMAP + enable the bridge on the gateway host:

```bash
export ABSTRACT_EMAIL_BRIDGE=1
export ABSTRACT_EMAIL_IMAP_HOST="imap.example.com"
export ABSTRACT_EMAIL_IMAP_USERNAME="me@example.com"
export ABSTRACT_EMAIL_IMAP_PASSWORD_ENV_VAR="EMAIL_PASSWORD"
export ABSTRACT_EMAIL_POLL_SECONDS=60
```

Recommended for v0: auto-start a workflow per thread/session:

```bash
export ABSTRACT_EMAIL_FLOW_ID="<bundle_id>:<flow_id>"
```

## Workflow wiring

Create a flow that:
1. handles `email.message` (On Event; scope `session`)
2. reads `payload.email.*` (subject/from/body and artifact-backed attachments)
3. optionally opens attachments via `open_attachment(artifact_id=...)`
4. replies with `send_email(...)`

## See also

Gateway maintenance docs mention the bridge and email inbox endpoints:
- https://github.com/lpalbou/abstractgateway/blob/main/docs/maintenance.md


--- docs/guide/process-manager-env-vars.md ---
# Process Manager Env Vars (Write-only) - Operator Guide

This guide explains how to configure a small allowlist of environment variables on the gateway host via AbstractObserver,
without exposing the values back to browsers/clients.

## What this is (and why)

- Goal: configure framework integrations (for example email) from the UI.
- Security model:
  - allowlist-only keys (no arbitrary env var editing)
  - write-only values (the gateway API never returns env var values)
  - values are persisted on the gateway host with restrictive file permissions

## Requirements

- Gateway process manager enabled: `ABSTRACTGATEWAY_ENABLE_PROCESS_MANAGER=1`
- AbstractObserver connected to that gateway

## Where values are stored (host-side)

- `<ABSTRACTGATEWAY_DATA_DIR>/process_manager/env_overrides.json`

## How values are applied

- When you set/unset an allowlisted env var in the UI:
  - the gateway persists it to `env_overrides.json`
  - the gateway applies it to its own `os.environ` (so integrations reading env vars can see it)
- When the process manager launches managed processes, it merges:
  1. gateway `os.environ`
  2. allowlisted overrides
  3. per-process env (static)

If a service reads env vars only at startup, restart that service after changing env vars.

## Allowlisted keys

The allowlist is gateway-defined. Email-related keys are commonly allowlisted for inbox and SMTP defaults.

## See also

- AbstractGateway docs: https://github.com/lpalbou/abstractgateway


--- docs/backlog/overview.md ---
# AbstractFramework Backlog Overview

This root backlog is the framework-level planning ledger for cross-package work. Some older items
use legacy naming and duplicate numeric prefixes; new items should use four-digit global IDs and
the lifecycle folders described by the backlog process.

## Current Counts

- Planned: many legacy items plus active cross-package work.
- Proposed: legacy proposed items exist.
- Completed: historical completion ledger exists under `completed/`.
- Deprecated: not yet normalized at the root level.
- Recurrent: not yet normalized at the root level.

## Active Planned Work

| ID | Item | Status | Notes |
|----|------|--------|-------|
| 0142 | [Gateway tenant isolation and shared runtime design](planned/0142_gateway_tenant_isolation_and_shared_runtime.md) | Planned | Define and implement tenant-aware Gateway/Runtime isolation; current shared Gateway deployments are single-user or trusted-cohort only. |
| 0143 | [Shared Gateway per-principal runtime router](planned/0143_shared_gateway_per_principal_runtime_router.md) | In progress | Gateway principal auth, admin user CRUD, per-principal GatewayService routing, and Flow browser-session routing landed; broader app auth and route-family isolation remain open. |
| 0145-0153 | [Gateway control plane track](planned/gateway-control-plane/README.md) | Planned | Gateway-owned admin/account/config/workflow-permission control plane; starts with responsibility, RBAC, and browser-session contracts before broad UI/app migration. |

## Gateway Control Plane Planned Track

| ID | Item | Status | Notes |
|----|------|--------|-------|
| 0145 | [Gateway admin console bootstrap](planned/gateway-control-plane/0145_gateway_admin_console_bootstrap.md) | In progress | Console v0 now serves `/console` with session sign-in, account/runtime summary, admin user management, optional email, create/delete confirmations, token rotation, and discovered provider/model defaults; richer runtime activity remains optional follow-up. |
| 0146 | [Gateway RBAC scope policy matrix](planned/gateway-control-plane/0146_gateway_rbac_scope_policy_matrix.md) | In progress | Central route-family policy gates operator/server-workspace/model-residency surfaces, runtime ids are tenant-unique, and the Alice/Bob matrix now covers runs, ledgers, artifacts, session artifacts, KG/session memory, private workflows, prompt-cache naming, defaults overlays, workspace helper denials, and discovery leak behavior. |
| 0147 | [Gateway per-principal config, secrets, and defaults](planned/gateway-control-plane/0147_gateway_per_principal_config_secrets_defaults.md) | In progress | Gateway-baseline plus per-user capability-default overlays and console UX landed; raw provider-secret storage/injection remains deliberately deferred pending a Core/Gateway secret boundary. |
| 0148 | [Gateway workflow registry ACLs](planned/gateway-control-plane/0148_gateway_workflow_registry_acl.md) | In progress | Immutable tenant catalog versions, admin default pointers, ACL APIs, explicit catalog scope, signed run-start/schedule policy, host-side catalog guards, ACL-aware catalog inspection, and discovery metadata landed; per-tool/workspace/secret policy intersection and UI remain. |
| 0150 | [Observer and Manager responsibility split](planned/gateway-control-plane/0150_observer_manager_responsibility_split.md) | Planned | Early containment audit to keep Observer focused on observability and admin/config ownership in Gateway/Gateway Console or later Manager surfaces. |
| 0153 | [Gateway browser session security contract](planned/gateway-control-plane/0153_gateway_browser_session_security_contract.md) | In progress | Gateway/Flow opaque browser sessions, CSRF, logout, token-rotation revocation, Code/Observer hosted proxy convergence, and HTTP/HTTPS/origin/expiry/logout/revocation cookie matrix tests landed. |

## Active Proposed Work

| ID | Item | Status | Notes |
|----|------|--------|-------|
| 0144 | [User profile metadata for selective model grounding](proposed/0144_user_profile_context_grounding.md) | Proposed | Discuss first/last name, birth date, inferred country, provenance, and query-time selective context injection before implementation. |
| 0151 | [Runtime Explorer contract](proposed/gateway-control-plane/0151_runtime_explorer_contract.md) | Proposed | Reviewer consensus: start with a read-only Gateway envelope contract and Observer page for typed runtime resources; defer `abstractexplorer`, delete/export, raw workspace browsing, and admin cross-user exploration. |
| 0152 | [AbstractManager package extraction](proposed/gateway-control-plane/0152_abstractmanager_package_extraction.md) | Proposed | Revisit a separate `abstractmanager` package only after console/config/workflow ACL surfaces prove real maintenance or reuse pressure. |
| 0155 | [Hosted proxy shared helper extraction](proposed/gateway-control-plane/0155_hosted_proxy_shared_helper_extraction.md) | Proposed | Keep conformance tests now; extract a shared Node helper only if Code/Observer or future hosted apps drift again. |

## Recent Completed Work

| ID | Item | Completed | Notes |
|----|------|-----------|-------|
| 0157 | [Gateway provider endpoint profiles](completed/0157_gateway_provider_endpoint_profiles.md) | 2026-05-31 | Added Gateway-owned provider endpoint profiles with descriptions, write-only API keys, virtual `endpoint:*` providers in discovery, Runtime resolution, local dynamic provider construction, console UI with model discovery, and tests. |
| 0156 | [Retained runtime admin lifecycle](completed/0156_retained_runtime_admin_lifecycle.md) | 2026-05-30 | Added admin-only retained runtime list/transfer/purge routes, Gateway Console actions, scoped purge deletion, transfer semantics, and regression tests. |
| 0154 | [Multi-user security release blockers](completed/0154_multi_user_security_release_blockers.md) | 2026-05-30 | Added retained-runtime reservations, Code/Observer hosted URL guards, published launcher user bootstrap, and `.DS_Store` cleanup. |
| 0149 | [Cross-app Gateway auth and defaults convergence](completed/0149_cross_app_gateway_auth_defaults_convergence.md) | 2026-05-30 | Per-app hosted/local auth/default matrix completed; Flow, Code Web, and Observer use hosted browser-session proxy auth; shared auth/default component intentionally deferred until duplication creates real pressure. |
| 0141 | [Flow browser-session Gateway auth](completed/0141_flow_browser_session_gateway_auth.md) | 2026-05-30 | Initial Flow browser sign-in removed server/admin ambient browser auth; 0153 now supersedes raw token cookies with opaque Gateway browser sessions. |
| 0140 | [Abstract Release Skill](completed/0140_abstract_release_skill.md) | 2026-05-24 | Added a read-only framework release orchestration skill with package discovery, release-wave planning, dependency-floor review, root profile pin drift checks, PyPI visibility gates, and approval/traceability guidance. |
| 0139 | [Unified Framework Capability Defaults](completed/0139_unified_framework_capability_defaults.md) | 2026-05-24 | Core-owned routing defaults for input/output/embedding/rerank, Gateway control-plane access, atomic provider/model resolution, catalog-backed Flow defaults UI, and qwen3.6 text default. |

## Operating Notes

- Use `docs/adr/` for durable architecture policy.
- Use this backlog for execution traceability, validation evidence, and follow-up state.
- New backlog item filenames should use `NNNN_<slug>.md`; date-prefixed legacy files should not be copied for new work.

--- docs/backlog/completed/0141_flow_browser_session_gateway_auth.md ---
# Completed: Flow browser-session Gateway auth

## Metadata
- Created: 2026-05-29
- Status: Completed
- Completed: 2026-05-30

## ADR status
- Governing ADRs: ADR-0018, ADR-0033
- ADR impact: May revise existing ADR

## Context
AbstractFlow's browser editor uses a Flow server/proxy to inject Gateway auth
into `/api/gateway/*` requests. Browser login is now scoped to the browser
session and does not treat server/admin tokens as browser login state. This
item describes the initial Flow-side boundary; planned item 0153 supersedes the
raw token cookie implementation with opaque Gateway browser sessions and CSRF.

## Current code reality
- `abstractflow/web/backend/services/gateway_connection.py` persists only the
  Gateway URL and resolves browser auth only from session cookies.
- `abstractflow/web/backend/routes/connection.py` validates submitted user tokens
  through Gateway `/me`, rejects admin/server principals, and sets only
  HTTP-only browser cookies.
- `abstractflow/web/frontend/bin/cli.js` and
  `abstractflow/web/frontend/vite.config.ts` use the same browser-cookie
  session model for status and proxy auth.
- `abstractflow/web/frontend/src/components/GatewayConnectionModal.tsx` presents
  Gateway URL, user, and Gateway token; tenant/runtime are returned by Gateway
  as read-only principal metadata.

## Problem
The original problem was that server-configured Gateway tokens could become
ambient browser auth. The current implementation removes that fallback for
browser requests.

## What we want to do
Keep browser-session authentication as the default AbstractFlow hosted behavior
so each browser/user must authenticate and only receives access to its own
Gateway connection state.

## Why
Hosted Flow deployments need a clear security boundary. Gateway tokens are control-plane credentials and must not become ambient shared credentials for every browser that can load the Flow UI.

## Requirements
- Store Gateway connection state per browser session, not as a single global
  process token.
- Ensure `/api/gateway/*` proxy injection resolves the token from the browser
  session.
- Preserve local loopback ergonomics while still requiring browser sign-in.
- Keep Gateway bearer tokens out of browser `localStorage`/`sessionStorage`.
- Make remote Gateway URL changes explicit through
  `ABSTRACTFLOW_ALLOW_REMOTE_BROWSER_GATEWAY_CONFIG`.

## Suggested implementation
- Use HTTP-only browser cookies for Gateway URL/token session state.
- Remove `CONNECTION.gatewayToken`/`ABSTRACTGATEWAY_AUTH_TOKEN` fallback use from
  browser status and proxy paths.
- Teach the Python FastAPI host, Node static server, and Vite dev proxy the
  same session resolution semantics.

## Scope
- AbstractFlow web backend connection routes.
- AbstractFlow Node static server connection/proxy path.
- Vite dev connection/proxy path.
- Documentation and security guidance for hosted Flow deployments.

## Non-goals
- Do not change AbstractGateway's own bearer-token model in this item.
- Do not store Gateway tokens in browser storage.
- Do not make public multi-user hosting depend on a single shared Gateway token unless explicitly configured by the operator.

## Dependencies and related tasks
- ADR-0018 durable gateway/control-plane model.
- ADR-0033 install profiles and server boundaries.
- `abstractflow/docs/web-editor.md`
- `abstractflow/docs/architecture.md`
- `abstractflow/web/backend/routes/connection.py`
- `abstractflow/web/frontend/bin/cli.js`

## Expected outcomes
- A distinct browser session connecting to the same hosted Flow server cannot use another session's Gateway token.
- Hosted Flow can require each browser/user to authenticate or provide its own token.
- Local single-user development remains easy and documented.

## Validation
- Unit/integration test with two browser clients and separate cookies proves isolation.
- Regression test proves loopback local configuration still works.
- Proxy auth tests prove `/api/gateway/*` injects the session token, not a stale process-global token.
- Documentation explains local, single-user hosted, and multi-user hosted security modes.

## Progress checklist
- [x] Choose session/auth store design and hosted-mode defaults.
- [x] Implement Python backend session-scoped connection storage.
- [x] Implement Node static server session-scoped connection storage.
- [x] Align Vite dev proxy behavior for local development.
- [x] Add browser-session proxy isolation tests.
- [x] Update Flow security docs and generated docs indexes.

## Follow-up guidance
Keep browser-session auth as the default Flow behavior. Future work should add
CSRF/session-hardening tests and extend the same current-user auth model to
Code, Assistant, Observer, and bridge-hosted app flows.

--- docs/backlog/planned/0142_gateway_tenant_isolation_and_shared_runtime.md ---
# Planned: Gateway tenant isolation and shared runtime design

## Metadata
- Created: 2026-05-29
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: May revise existing ADR

## Context
AbstractGateway currently uses bearer-token security for the gateway API
surface. In user-auth mode, bearer tokens resolve to a user principal and
Gateway can route each principal to a separate runtime/data plane. AbstractFlow
uses browser-session cookies for user tokens and does not let a server/admin
token become shared browser login state.

The present model is suitable for local single-user deployments and trusted
cohorts. It is not a multi-user isolation model for independent users.

## Current code reality
- `abstractflow/web/backend/main.py`, `abstractflow/web/frontend/bin/cli.js`, and
  `abstractflow/web/frontend/vite.config.ts` proxy `/api/gateway/*` and inject
  the signed-in browser session's Gateway user token.
- `abstractgateway/src/abstractgateway/security/gateway_security.py` validates
  global bearer tokens and origin policy, but does not resolve a tenant/user
  principal.
- Gateway run, ledger, command, artifact, KG, prompt-cache, and VisualFlow
  routes are scoped by ids and request parameters, not by authenticated owner.
- AbstractRuntime state carries `actor_id` and `session_id`; those are
  provenance/correlation fields, not authorization boundaries.
- Memory owner ids include run/session/global concepts; global means the runtime
  instance's global owner, not a tenant-isolated namespace.

## Problem
If several independent users share one Flow/Gateway/runtime/data plane today,
one user can potentially list or access another user's run metadata, ledgers,
history bundles, artifacts, prompt-cache state, workflow mutations, memory, tool
execution surface, workspace effects, provider credentials, and audit scope.
`session_id`, `run_id`, `artifact_id`, and `owner_id` are not safe authorization
proofs.

## What we want to do
Define and implement a tenant-aware Gateway architecture that supports
independent users safely. Until that exists, document and enforce the supported
deployment pattern: an authenticated front door routes each user or tenant to a
separate Gateway/runtime/data plane.

## Why
Gateway is the durable control plane. Shared use without tenant authorization
risks confidentiality leaks, integrity failures, workspace/file access problems,
memory poisoning, credential bleed, and weak auditability.

## Requirements
- Add a `Principal` or `TenantContext` resolved from trusted Gateway auth.
- Persist `tenant_id`, `user_id`, roles/scopes, and token fingerprint on runs and
  audit records without logging bearer tokens.
- Enforce tenant filtering for run list/detail, ledger replay/stream, history,
  commands, artifacts, uploads/import/export, prompt cache, workflow CRUD/publish,
  KG/memory owner access, workspace policy, tool execution, and provider
  credentials.
- Treat `session_id`, `run_id`, `artifact_id`, and `owner_id` as references only;
  never as authorization.
- Make `global` memory tenant-global by default; cross-tenant shared memory must
  be an explicit namespace with provenance, consent, deletion, and poisoning
  controls.
- Keep local single-user ergonomics through an explicit single-tenant default.
- Add two-user isolation tests across the control plane and stores.

## Suggested implementation
1. Near term: deploy an identity-aware front door that routes each authenticated
   user or tenant to a separate Gateway process, data dir, artifact store, memory
   store, workspace root, provider credential set, and quota bucket.
2. Add Gateway token-to-principal mapping for single-process deployments, but keep
   it single-tenant until storage and route enforcement are complete.
3. Introduce tenant/user columns or metadata in run stores, artifact metadata,
   prompt-cache keys, memory owner ids, workflow records, and audit logs.
4. Centralize authorization checks in service/storage layers so route handlers
   cannot accidentally bypass tenant filtering.
5. Admin-gate or disable global enumeration paths (`scope=all`, arbitrary
   `owner_id`, `all_owners`, broad artifact search, workflow mutation, and local
   tools) until tenant-aware policy exists.

## Scope
- AbstractFlow hosted connection model.
- AbstractGateway auth, routes, stores, artifact handling, memory/KG access,
  prompt-cache routes, workflow CRUD/publish, commands, audit, and workspace
  policy.
- AbstractRuntime run state and store schemas where tenant ownership must be
  durable.
- Documentation, ADRs, and release gates for supported deployment topologies.

## Non-goals
- Do not claim current shared Gateway deployments are tenant-isolated.
- Do not use caller-supplied `session_id`, `actor_id`, `owner_id`, or headers as a
  trusted identity source.
- Do not make cross-user learning implicit. Shared/org memory must be explicit
  and auditable.
- Do not treat workspace scoping or `execute_command` as an OS sandbox.

## Dependencies and related tasks
- `docs/backlog/completed/0141_flow_browser_session_gateway_auth.md`
- `abstractgateway/docs/backlog/proposed/2026-05-13_shared_identity_context.md`
- ADR-0018 durable Gateway/control-plane contract.
- ADR-0021 deployment topologies and supported scenarios.
- ADR-0033 install profiles and server boundaries.

## Expected outcomes
- Operators can choose between clearly documented single-tenant, trusted-cohort,
  and future shared-tenant modes.
- Independent users cannot enumerate or access each other's runs, artifacts,
  memory, workflow mutations, workspaces, credentials, prompt-cache state, or
  audit details.
- Shared memory/cross-user learning is opt-in, provenance-rich, revocable, and
  separate from private user/tenant memory.

## Validation
- Two-user integration tests for Flow proxy sessions, Gateway runs/list/history,
  ledger stream/replay, commands, artifact search/content/upload/import/export,
  KG/memory queries, prompt-cache routes, VisualFlow CRUD/publish, workspace
  tools, and local tool execution policy.
- Store-level tests proving tenant filters are enforced below route handlers.
- Security docs and ADR checks confirming shared Gateway is not advertised as
  isolated before the tenant model lands.

## Progress checklist
- [ ] Finalize principal/tenant data model and single-tenant compatibility mode.
- [ ] Implement per-user/per-tenant Flow connection routing or front-door contract.
- [ ] Persist tenant/user ownership on Gateway and Runtime records.
- [ ] Enforce tenant filtering in Gateway service/store layers.
- [ ] Add two-user authorization test matrix.
- [ ] Document shared memory and cross-user learning as explicit opt-in.

## Guidance for the implementing agent
Start from code reality, not desired UX. Add authorization at the lowest shared
storage/service layer available, then wire routes to it. Preserve single-user
local ergonomics, but fail closed for shared hosted deployments.

--- docs/backlog/planned/0143_shared_gateway_per_principal_runtime_router.md ---
# Planned: Shared Gateway per-principal runtime router

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: May revise existing ADR

## Context
A shared AbstractGateway front door can be the right hosted architecture when it
acts as an authenticated router/control plane and routes each principal to an
isolated runtime/data plane. This avoids a separate public Gateway URL per user
while preserving the isolation properties of separate runtimes.

An adversarial review compared the strongest pro and con arguments. Both sides
converged on the same boundary: the design is sound if the shared Gateway routes
to isolated per-user or per-tenant `GatewayService`/Runtime contexts. It is not
sound if the Gateway keeps one shared service/stores/runtime and merely adds
`user_id` labels.

## Current code reality
- `abstractgateway/src/abstractgateway/security/gateway_security.py` validates
  global bearer tokens and origin policy. It does not currently resolve a
  trusted `Principal` with `tenant_id`, `user_id`, roles, or scopes.
- `abstractgateway/src/abstractgateway/service.py` exposes a singleton
  `GatewayService` with one config, one store set, one host, one runner, one
  auth policy, one embedding client, and optional bridges.
- `abstractgateway/src/abstractgateway/stores.py` builds one file or SQLite
  store set rooted at the configured Gateway data directory.
- `abstractgateway/src/abstractgateway/routes/gateway.py` has many endpoints
  that operate on caller-supplied ids such as `run_id`, `session_id`,
  `artifact_id`, and `bundle_id`. Those ids are references, not authorization
  proofs.
- Session memory owner ids are derived from caller-controlled session ids in
  several paths; global memory is runtime-instance global, not tenant global.
- VisualFlow/bundle publish, artifact search/listing, workspace/file helpers,
  prompt-cache routes, maintenance/process-manager routes, Telegram/email
  bridges, and background command processing are currently designed around the
  singleton service/data-plane shape.

## Problem
Hosted Flow/Gateway needs a multi-user story that is both ergonomic and safe.
One Gateway per user is conceptually simple but operationally heavy: it creates
endpoint sprawl, certificate/domain management overhead, duplicated routing,
harder upgrades, version skew, and more complicated Flow connection UX.

A single shared Gateway front door can solve those operational issues, but a
partial implementation can be worse than no implementation. Routing only LLM
calls per user while leaving runs, ledgers, artifacts, commands, memory,
workspaces, prompt cache, bundles, provider credentials, or background workers
global would still leak or mix users.

## What we want to do
Introduce a hosted-mode architecture where:

```text
Flow/browser
  -> authenticated shared Gateway front door
    -> trusted principal resolution
      -> server-side principal-to-runtime routing
        -> isolated GatewayService / Runtime context
          -> isolated stores, memory, artifacts, workspace, secrets, queues
```

The first implementation should prefer isolated per-principal data planes over
shared stores with tenant columns. A single process may hold several
per-principal service objects, but each object must own its own data directory,
stores, runner/queue, workspace root, provider defaults, secret scope, memory,
artifact store, and prompt-cache namespace.

## Why
This architecture keeps the hosted product manageable while preserving the main
security benefit of per-user runtimes. It gives Flow one stable API endpoint and
lets login determine identity and runtime selection. It also creates a better
foundation for later org/team features: admin consoles, billing, quotas, scoped
collaboration, audit, and explicit shared memory.

## Requirements
- Add a trusted `Principal` model resolved by Gateway auth middleware or a
  trusted front-door integration. It should include at least `tenant_id`,
  `user_id`, roles/scopes, and token/session fingerprint metadata.
- Gateway owns hosted-mode authentication. Apps such as AbstractFlow,
  AbstractCode, AbstractAssistant, and AbstractObserver must authenticate as the
  current user/session and forward only trusted Gateway credentials or cookies;
  they must not share one app-server Gateway token across all browser users.
- Add admin-level user management routes for Gateway operators to list, create,
  update, disable, delete, and rotate credentials for users. These routes must
  require an admin principal and must never disclose stored token hashes.
- Clients must not send authoritative `user_id`, `tenant_id`, `runtime_id`, or
  workspace root values. If accepted for UX, they must be advisory and checked
  against server-side policy.
- Add a server-side `Principal -> RuntimeContext/GatewayService` router.
- Each per-principal context must own an isolated data plane:
  - data directory;
  - run store and ledger store;
  - command inbox/cursor store and runner;
  - artifact store;
  - memory/KG owner namespace or store;
  - prompt-cache/bloc namespace or disabled hosted-mode prompt cache;
  - workspace root and mount policy;
  - provider defaults, credentials, quotas, and secrets.
- Admin/global endpoints must be separated from user endpoints. Hosted mode
  should disable or admin-gate unscoped global enumeration and mutation paths.
- Bundles/VisualFlows must be either tenant-local or global read-only with
  admin-only publishing.
- Every read/write path must authorize against the resolved principal, including
  run start/list/detail, ledger replay/SSE, history bundle, resume/cancel,
  commands, artifacts, uploads/import/export, memory/KG, prompt cache, workflow
  CRUD/publish, workspace/file tools, provider config, maintenance routes, and
  bridge-triggered runs.
- Background workers must carry tenant context through queued commands, child
  runs, event emission, artifact projection, and resume paths.
- Logs, traces, temporary files, metrics, audit records, and error reports must
  avoid unscoped user content or include principal-safe ownership metadata.

## Suggested implementation
1. Add a principal abstraction and middleware hook, but keep local single-user
   mode as a default principal.
2. Introduce a `GatewayServiceRouter` composition root that returns the current
   principal's service/context instead of the process-wide singleton service.
   In the first code slice, preserve the public `get_gateway_service()` helper
   but make it resolve through a request context variable when hosted user auth
   is enabled. This lets the existing route surface inherit per-principal data
   planes before every endpoint is converted to explicit dependencies.
3. Implement hosted v0 using separate data directories and store sets per
   principal. Avoid a shared DB/schema migration in the first version.
4. Add `/api/gateway/me` and `/api/gateway/admin/users` before app-specific
   login UX so Flow and native apps can test the resolved principal contract.
5. Move route dependencies from `get_gateway_service()` to
   `get_gateway_service_for_principal(...)` or an equivalent request-scoped
   dependency as route families are touched.
6. Make global/admin surfaces explicit and fail closed in hosted mode:
   broad artifact search, `scope=all`, arbitrary owner ids, workflow publishing,
   process manager, backlog execution, local workspace tools, bridge admin
   config, and provider credential mutation.
7. Add app-auth adapters: browser apps should rely on Gateway session cookies or
   request-bound user bearer tokens, while native apps should use user API
   tokens/device login. All apps should call `/api/gateway/me` after connect.
8. Add a two-user test harness that tries guessed ids across every route family.

## Scope
- AbstractGateway security, service composition, routes, stores, runner,
  artifacts, workflow/bundle registry, memory/KG integration, prompt cache,
  workspace policy, provider defaults, maintenance routes, and bridge entry
  points.
- AbstractRuntime ownership context where run state, child runs, memory owner
  ids, prompt-cache bindings, and artifact projection need durable tenant
  provenance.
- AbstractFlow hosted connection UX for identity-aware Gateway discovery and
  no browser-controlled runtime selection.
- Documentation and ADR updates for supported hosted topologies.

## Non-goals
- Do not build a shared `GatewayService`/store set with only `user_id` labels as
  the first version.
- Do not claim that the current Gateway bearer token model provides per-user
  isolation.
- Do not trust caller-supplied `session_id`, `run_id`, `artifact_id`,
  `owner_id`, or `bundle_id` as authorization.
- Do not make cross-user memory or learning implicit. Shared/team memory must be
  a later explicit namespace with consent, ACLs, audit, deletion semantics, and
  poisoning controls.
- Do not turn workspace scoping into a claimed OS sandbox.
- Do not expose per-user runtime URLs or internal routing identifiers to the
  browser as control inputs.

## Dependencies and related tasks
- `docs/backlog/completed/0141_flow_browser_session_gateway_auth.md`
- `docs/backlog/planned/0142_gateway_tenant_isolation_and_shared_runtime.md`
- `abstractgateway/docs/backlog/proposed/2026-05-13_shared_identity_context.md`
- ADR-0018 durable Gateway/control-plane contract.
- ADR-0021 deployment topologies and supported scenarios.
- ADR-0033 install profiles and server boundaries.

## Expected outcomes
- Hosted Flow can connect to one public Gateway endpoint while each
  authenticated user/tenant receives an isolated runtime/data plane.
- Alice cannot enumerate, read, stream, resume, cancel, export, import, mutate,
  or infer Bob's runs, ledgers, artifacts, sessions, memory, prompt cache,
  workspaces, bundles, provider credentials, or command inbox.
- Gateway operators can run local single-user mode, trusted-cohort mode, or
  hosted per-principal runtime-router mode with explicit documentation.
- Shared/team memory and collaboration remain future explicit product features,
  not accidental leakage from shared infrastructure.

## Validation
- Unit tests for principal extraction, token/session fingerprinting, scope
  checks, and service-router selection.
- Two-user integration tests proving guessed `run_id`, `session_id`,
  `artifact_id`, `bundle_id`, and memory owner ids cannot cross principals.
- SSE/ledger/history tests proving streams and batch replay are principal-bound.
- Command/resume/cancel tests proving queued records carry tenant context.
- Artifact upload/list/search/content/export/import tests with Alice/Bob data.
- VisualFlow/bundle tests for tenant-local or admin-only global publishing.
- Workspace/file-tool tests proving hosted mode uses per-principal roots and
  rejects arbitrary absolute roots.
- Prompt-cache tests proving hosted mode scopes or disables shared cache state.
- Audit/log checks proving bearer tokens are never logged and user content is
  scoped/redacted.

## Progress checklist
- [x] Run adversarial two-subagent review for the shared Gateway router design.
- [x] Define `Principal` and hosted-mode auth contract.
- [x] Add admin user registry and admin-only CRUD routes.
- [x] Design `GatewayServiceRouter` and local single-user compatibility mode.
- [x] Implement per-principal data directories and service contexts.
- [x] Convert existing route dependencies to request-scoped service lookup via
      the `get_gateway_service()` composition root.
- [ ] Admin-gate or disable global surfaces in hosted mode.
- [ ] Carry principal context through runner/command/background paths.
- [x] Add `/api/gateway/me` and app policy display.
- [x] Change AbstractFlow hosted auth to current-user Gateway credentials rather
      than one app-server token.
- [ ] Change AbstractCode/Assistant/Observer hosted auth to current-user Gateway
      credentials rather than one app-server token.
- [ ] Add the two-user isolation test matrix.
- [ ] Update ADRs and hosted deployment docs.

## Review notes: 2026-05-30
Two independent subagent reviews agreed that a shared Gateway can scale as a
control-plane/router only if the per-user data planes are separate. The first
implementation should therefore add identity resolution, admin user CRUD, and
request-scoped service routing before attempting route-by-route tenant columns.

The reviews also called out a hard boundary for hosted apps: AbstractFlow and
other frontends cannot safely use one server-held Gateway token for all users.
They need a current-user auth/session path that lets Gateway resolve the
principal and route to that user's runtime. Until that app-auth migration is
finished, hosted multi-user deployments must be treated as an incremental beta
surface rather than a complete isolation guarantee across every app workflow.

## Implementation report: 2026-05-30
- Added `GatewayPrincipal`, request context propagation, and legacy-token
  compatibility where `ABSTRACTGATEWAY_AUTH_TOKEN` resolves to `local-admin`.
- Added a file-backed `GatewayUserRegistry` at
  `<ABSTRACTGATEWAY_DATA_DIR>/auth/users.json` by default. User tokens are
  PBKDF2-SHA256 hashed; generated/rotated tokens are returned once.
- Added `GET /api/gateway/me` and admin-only
  `/api/gateway/admin/users` list/create/read/update/delete routes.
- Added request-scoped service routing: when user auth is enabled,
  `get_gateway_service()` resolves the current principal and returns a
  per-principal `GatewayService` with separate runtime/flows directories under
  `<DATA_DIR>/users/<tenant_id>/<runtime_id>/`.
- Kept local/single-user Gateway behavior compatible: without user auth, the
  process-wide singleton service and legacy token model remain.
- Changed AbstractFlow hosted connection handling so remote browser sessions
  sign in with Gateway URL, Gateway user id, and user token. Flow validates that
  Gateway `/me` resolves to that expected user before accepting the connection.
  Gateway owns the user's tenant/runtime mapping and returns it as read-only
  principal metadata. This was later hardened by 0153: Flow now exchanges the
  user token for an opaque Gateway browser session, keeps only the session id in
  an HTTP-only browser cookie, and forwards the session plus CSRF token for
  mutating Gateway proxy calls. Different browsers must connect as their own
  Gateway users.
- Simplified the AbstractFlow modal to the three intended fields
  (`Gateway URL`, `User`, `Gateway token`), removed the tenant/runtime input,
  renamed the primary action to sign in, and made the resolved runtime a
  read-only status detail returned by Gateway.
- Hardened the Flow Gateway proxy so browser-supplied `Authorization`, `Cookie`,
  `X-Forwarded-*`, and other unapproved headers are stripped before proxying;
  Flow injects only the resolved Gateway browser session.
- Hardened Gateway admin routes so they fail closed if the router is mounted
  without `GatewaySecurityMiddleware` while Gateway security is enabled.
- Updated Gateway and Flow docs plus `llms.txt`/`llms-full.txt` files to
  describe the new auth/routing contract and remaining hosted-mode limits.

Remaining work is intentionally still open: admin-gating every global/operator
route family, carrying principal context through every background/bridge path,
changing Code/Assistant/Observer hosted auth, and expanding the Alice/Bob
guessed-id isolation matrix across run, artifact, memory, workspace,
prompt-cache, process, and maintenance endpoints.

## Guidance for the implementing agent
Start by preserving the strong isolation boundary: separate per-principal data
planes. Resist the shortcut of adding owner labels to the existing singleton
service. Add authorization at the lowest shared layer available, not only in
route handlers. Re-run the adversarial review before promoting shared stores,
shared prompt cache, shared memory, or collaborative features.

--- docs/backlog/planned/gateway-control-plane/README.md ---
# Gateway control plane backlog track

## Status
Planned/in progress, with adjacent proposals for package extraction decisions.
Gateway/Flow now have browser-session auth, central route-family authorization,
the first Gateway Console, Gateway-baseline plus per-user capability-default
overlays, secret-free browser login responses, full Gateway cookie/origin
session matrix tests, an extended Alice/Bob isolation matrix for the current
user-owned data surfaces, retained-runtime reservations after user deletion,
retained-runtime transfer/purge lifecycle, and completed cross-app auth/default
convergence planning. Gateway provider endpoint profiles now cover the first
secret-safe reusable endpoint path. The track remains open for future
route-family growth, workflow ACL UI, runtime exploration contracts, and a
fuller provider-secret vault/bridge policy.

## Purpose
This track groups the Gateway admin/account/config/runtime-control work raised
by the multi-user Gateway review. Gateway is the trust boundary and control
plane; Flow, Code, Observer, and Assistant should become task UIs that consume
Gateway auth, defaults, permissions, and catalogs instead of each owning global
identity or model configuration.

## Items
- `0145_gateway_admin_console_bootstrap.md`: Gateway-served admin/account console v0.
- `0146_gateway_rbac_scope_policy_matrix.md`: route-family role/scope hardening.
- `0147_gateway_per_principal_config_secrets_defaults.md`: per-principal config, provider keys, and defaults through Gateway with Core as schema/persistence authority.
- `0148_gateway_workflow_registry_acl.md`: private workflow registry plus tenant/framework catalog ACLs.
- `0150_observer_manager_responsibility_split.md`: keep Observer focused and move admin/config ownership out.
- `0153_gateway_browser_session_security_contract.md`: define hosted browser session, cookie, CSRF, logout, and revocation semantics.

Adjacent proposals:
- `../../proposed/gateway-control-plane/0151_runtime_explorer_contract.md`
- `../../proposed/gateway-control-plane/0152_abstractmanager_package_extraction.md`

Completed in this track:
- `../../completed/0149_cross_app_gateway_auth_defaults_convergence.md`: converged Flow, Code Web, Observer, Gateway Console, Assistant, and automation behavior expectations for hosted/local auth and defaults; shared component extraction is deferred.
- `../../completed/0154_multi_user_security_release_blockers.md`: closed the retained-runtime reuse, Code/Observer hosted Gateway URL guard, published launcher bootstrap, and `.DS_Store` hygiene release blockers.
- `../../completed/0156_retained_runtime_admin_lifecycle.md`: added explicit admin list/transfer/purge lifecycle for retained runtime reservations.
- `../../completed/0157_gateway_provider_endpoint_profiles.md`: added Gateway-owned endpoint profiles that surface as virtual `endpoint:*` providers with write-only credentials.

## Reading order
Continue by keeping `0146` and `0153` tests current as new route families and
browser apps appear. `0145` now has a narrow console v0 with user email, confirmations,
    and discovered provider/model selectors; keep it narrow. `0147` now has a
Gateway baseline, per-principal defaults, and the initial Gateway provider
endpoint profile injection boundary; encryption, bridge, delegated-tool, and
audit policy remain. Use `0148` after the
authorization/session boundaries are stable, with immutable catalog versions
and explicit default pointers. `0149` is complete; do not extract a shared auth
component until duplication creates a real maintenance problem. Keep `0151`,
`0152`, and `0155` proposed until overlap, package pressure, or repeated hosted
proxy drift is proven.

## Relevant ADRs and docs
- ADR-0018: Durable Run Gateway and Remote Host Control Plane.
- ADR-0021: Deployment topologies and supported scenarios.
- ADR-0033: Install profiles, config entrypoints, and server boundaries.
- ADR-0035: Capability routing defaults.
- `docs/guide/capability-routing-defaults.md`
- `docs/guide/gateway-security.md`
- `docs/backlog/planned/0143_shared_gateway_per_principal_runtime_router.md`

## Non-goals
This track does not make Gateway a workflow authoring UI, coding UI, or rich run
trace viewer. Flow remains the workflow authoring surface. Code remains the
coding-agent UX. Observer remains the run/ledger observability UX unless future
proposals intentionally split runtime exploration into a new app.

--- docs/backlog/planned/gateway-control-plane/0145_gateway_admin_console_bootstrap.md ---
# Planned: Gateway admin console bootstrap

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: May revise existing ADR

## Context
Gateway now has concrete principals, user-registry auth, admin-only user CRUD,
and per-principal runtime routing. The first usable hosted experience still
requires operators to use raw routes or scripts to see who they are, create
users, rotate tokens, and understand what runtime a user owns.

## Current code reality
- `abstractgateway/src/abstractgateway/security/principal.py` defines
  `GatewayPrincipal.is_admin()` as the `admin` role check.
- `abstractgateway/src/abstractgateway/routes/gateway.py` exposes
  `/api/gateway/me` and admin-only `/api/gateway/admin/users`.
- `abstractgateway/src/abstractgateway/users.py` stores user records with
  hashed bearer tokens, roles, scopes, enabled state, and `runtime_id`.
- `scripts/gateway-flow-local.sh` now prepares `default/admin` by default and
  gives it roles `admin,user`.
- Gateway now serves a dependency-free console at `/console`, with `/`
  redirecting there. The console uses Gateway browser sessions, reads `/me`,
  lets admins manage `/admin/users`, and lets users edit per-principal
  capability defaults.
- The console now lists retained runtime reservations and lets admins explicitly
  transfer or purge them after confirmation.
- Console user creation now collects optional email contact metadata, asks for
  confirmation before creating/deleting users, and uses Gateway discovery
  endpoints for provider/model selection instead of free-text provider/model
  fields.

## Problem
Installing or hosting Gateway is opaque. Admins need a browser-visible control
plane for first-run account state, user creation, runtime assignment, token
rotation, and runtime summary. Normal users need an account/runtime page that
does not require raw API calls.

## What we want to do
Add a narrow Gateway-served console v0 at canonical `/console`, while keeping
OpenAPI docs at `/docs`. `/` may redirect to `/console` when the console is
enabled. The first version should focus on sign-in/session state, `/me`,
account/runtime summary, and admin user management only for routes already
covered by the RBAC policy matrix. Normal users should see their own
account/runtime state and token-management options that policy permits.

## Why
Gateway is the trust boundary. A clean built-in control-plane UX reduces setup
mistakes, avoids duplicating admin configuration in Flow/Observer/Code, and
makes the `1 user = 1 runtime` model visible.

## Requirements
- Admin mutation pages are blocked on `0146` enforcement for every route they
  call; frontend hiding is not authorization.
- First-run credential disclosure is local-dev/loopback only, never a hosted
  production pattern. Hosted deployments must use explicit operator bootstrap
  and rotation paths.
- Local-dev token display must avoid server logs, respect file permissions,
  explain the token cache/recovery path, and encourage rotation.
- Login follows the browser-session contract in `0153`: Gateway user tokens are
  exchanged for app/browser sessions and are not retained in browser storage.
- Admin views: list/create/update/disable/delete users, rotate tokens, assign
  runtime ids, collect optional account email, inspect roles/scopes, transfer or
  purge retained runtime reservations.
- User views: current principal, runtime id, created date, enabled state, token
  rotation if allowed, recent activity summary if available.
- Never display token hashes or existing bearer tokens after issuance.
- Keep `/docs` available for OpenAPI.

## Suggested implementation
Start with a small static app served by Gateway and backed by existing
`/api/gateway/me` and `/api/gateway/admin/users`. Reuse AbstractUIC visual
tokens/theme primitives where practical, but keep the first version small.

## Scope
- Gateway-served console route and static assets.
- Account page and admin user-management page.
- Minimal runtime summary endpoints if current API data is insufficient and
  `0146` authorizes the route family.
- Documentation for local and hosted setup.

## Non-goals
- Do not build workflow authoring into Gateway Console.
- Do not build full run trace visualization; link to Observer.
- Do not add per-user provider secret storage in this item; that is `0147`.

## Dependencies and related tasks
- `0146_gateway_rbac_scope_policy_matrix.md` (hard prerequisite for admin
  mutation UX)
- `0153_gateway_browser_session_security_contract.md`
- `0147_gateway_per_principal_config_secrets_defaults.md`
- `docs/backlog/planned/0143_shared_gateway_per_principal_runtime_router.md`
- `abstractgateway/docs/security.md`

## Expected outcomes
- A fresh local Gateway can be administered from a browser without raw curl.
- The default local prepared user is `admin`.
- Admin-only user CRUD remains enforced server-side.
- Normal users cannot access admin pages or admin APIs.

## Validation
- Unit/API tests for admin and non-admin console API access.
- Browser/manual check: admin can create a user and rotate token; normal user
  cannot.
- Security check: no token hashes or existing tokens are returned in user lists.

## Recent validation
- `python -m pytest abstractgateway/tests/test_gateway_security_middleware_unit.py abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_console.py abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py -q` -> 51 passed, 2 warnings.
- `python -m compileall -q abstractgateway/src/abstractgateway abstractflow/web/backend` -> passed.
- Earlier full-gateway validation: `python -m pytest abstractgateway/tests` -> 261 passed, 2 skipped.

## Progress checklist
- [x] Decide console route and static asset packaging.
- [x] Implement `0153` session semantics for console login.
- [x] Add account/runtime summary page.
- [x] Add admin user-management page after `0146` route checks exist.
- [x] Add minimal per-user defaults UX through `0147` overlay APIs.
- [x] Add retained-runtime reservation transfer/purge UX.
- [ ] Add richer runtime summary/activity API if needed.
- [x] Add tests and docs.

## Implementation note - 2026-05-30

Console v0 is implemented in `abstractgateway/src/abstractgateway/console.py`
and mounted from `abstractgateway/src/abstractgateway/app.py`. It intentionally
stays narrow: session sign-in/logout, account/runtime summary, admin user CRUD,
token rotation, retained runtime reservation lifecycle, and per-principal
capability-default editing. It does not own workflow authoring, deep runtime
exploration, or raw provider secret storage.

Follow-up console polish landed in the same track: provider/model defaults now
come from Gateway discovery selectors, admin create/delete uses confirmation
modals, and user records include optional email metadata for future
notification/invite workflows. User deletion currently removes account/token
access; runtime data retention/deletion must be handled by a separate retention
policy before destructive runtime cleanup is exposed.

2026-05-31 sign-in hardening: the console sign-in form now mirrors the shared
AbstractUIC Gateway browser-session sign-in card shape, omits Gateway URL
because `/console` is same-origin with Gateway, and has a generated JavaScript
syntax regression test so a malformed inline script cannot silently break the
login button again. React thin clients should use
`GatewaySessionSignInCard` from `@abstractframework/ui-kit`; the built-in
Gateway Console remains dependency-free static HTML and mirrors the same visual
contract.

## Guidance for the implementing agent
Keep this console narrow. If it starts becoming a full observability or workflow
authoring product, stop and split the concern into later items.

--- docs/backlog/planned/gateway-control-plane/0146_gateway_rbac_scope_policy_matrix.md ---
# Planned: Gateway RBAC scope policy matrix

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: Needs new ADR or ADR revision

## Context
Gateway has an `admin` role and admin-only user CRUD. Broader Gateway route
families are not yet governed by a complete role/scope matrix. The current
per-principal service router is a strong data-plane baseline, but route-family
authorization still needs explicit policy.

## Current code reality
- `GatewayPrincipal.is_admin()` is a string-role check.
- `/api/gateway/admin/users` is admin-gated.
- `/api/gateway/admin/runtime-reservations` list/transfer/purge routes are
  admin-gated.
- Non-admin users get per-principal data directories through Gateway service
  routing.
- Gateway now has a central authorization helper and a first route-family
  policy gate in the security middleware for admin, audit, process, backlog,
  triage, reports, capability-default writes, model load/unload, bloc writes,
  and prompt-cache writes.
- Gateway route-family policy is now centralized in
  `abstractgateway/src/abstractgateway/security/authorization.py`, and
  `GatewaySecurityMiddleware` delegates route-family checks to that table.
- Non-admin users can no longer satisfy admin-only route families via broad
  scopes such as `*`; `admin_required` means the `admin` role is required.
- Server-workspace file helpers, server-workspace artifact import/export, host
  metrics, email bridge routes, model residency listing, and model load/unload
  are admin-only in hosted user-auth mode. Browser file upload remains
  available to ordinary users.
- Capability-default writes are no longer treated as global admin writes in
  hosted user-auth mode; they are stored as per-principal overlays under the
  caller's runtime data plane by `0147`.
- Gateway user records now reject duplicate runtime ids within the same tenant,
  so `1 user = 1 runtime` cannot be accidentally broken by user creation or
  user update. Deleted users also leave a retained-runtime reservation, so a
  runtime whose data is retained cannot be assigned to a different principal in
  the same tenant unless an admin explicitly transfers the retained runtime or
  purges its data. The same runtime id can still exist in a different tenant.
- Per-principal routing is now covered by an initial Alice/Bob matrix for runs,
  run history, run input, ledger reads/streams/batches, artifact metadata,
  artifact content, and artifact search. Cross-user guessed ids return `404` or
  are omitted from batch/search results instead of returning empty records that
  imply existence.
- The Alice/Bob matrix now also covers private workflow bundles, VisualFlow
  drafts, per-principal capability-default overlays, session artifacts,
  prompt-cache key naming, and KG/session memory. Prompt-cache key hashing now
  includes a private principal scope while keeping the returned public identity
  app-level and portable.
- Capability discovery now reports admin-only server-workspace artifact
  import/export and provider prompt-cache control surfaces as unavailable for
  ordinary users, with machine-readable `admin_required` metadata. Admin
  principals still see those operations as available.
- `ABSTRACTGATEWAY_DEV_READ_NO_AUTH=1` now uses a non-admin
  `loopback-readonly` principal, and admin/operator route families still return
  machine-readable `403` denials.
- Powerful surfaces still need audit: workflow publish/remove/deprecate,
  workspace/file helpers, broader prompt-cache variants, provider defaults,
  credentials, broad runtime enumeration, bridge administration, discovery
  visibility, and global/operator endpoints.

## Problem
The words `admin` and `user` exist, but most of Gateway does not yet have a
decision-grade authorization matrix. Without one, future UI work can accidentally
surface privileged operations to ordinary users.

## What we want to do
Define and enforce a route-family RBAC/scope policy matrix for Gateway. The
matrix should state subject, action, resource class, owner/caller relation,
required role, required scope, audit requirement, discovery visibility, and
destructive/side-effect classification for each route family.

## Why
Gateway is now the shared control plane. Authorization must be centralized and
testable before Gateway Console, workflow catalog permissions, per-user
secrets, and runtime exploration can be trusted.

## Requirements
- Formalize at least `admin` and `user` roles plus concrete scope fields for
  narrow grants; do not leave downstream items to invent their own scope model.
- Model route authorization as subject/action/resource/condition checks, not
  scattered `if admin` branches.
- Admin-only: user management, credential/global config writes, global workflow
  catalog promotion/removal, process control, broad tenant/runtime enumeration,
  operator maintenance, and global policy changes.
- User-owned: own runs, ledgers, artifacts, memory, private workflows, and
  allowed runtime state.
- Explicit policy needed for shared/org memory, shared workspaces, workflow
  publishing, cross-runtime search, and destructive actions.
- Dev read bypass must never create a principal that satisfies `is_admin()`.
  Replace `local-admin` semantics with a distinct loopback/read-only principal,
  route allowlist, and tests proving admin/user/secret/catalog data remains
  unreachable.
- Denial responses and discovery metadata must not leak hidden resource ids,
  user existence, workflow existence, secret provider presence, or cross-runtime
  counts.
- Denials should be machine-readable, for example `reason_code`,
  `required_role`, `required_scope`, and `resource_class`, without exposing
  forbidden resource details.
- Admin/global writes and denied high-risk attempts are audit-log events.

## Suggested implementation
Add a centralized Gateway authorization helper and route-family policy table.
Refactor high-risk routes to call it. Keep denial reasons machine-readable so
UIs can hide or disable actions cleanly.

## Scope
- Gateway policy definitions and helper APIs.
- Route-family audits and tests.
- Discovery metadata for allowed/denied actions where clients need UX hints.

## Non-goals
- Do not implement the full Gateway Console here.
- Do not rely on frontend hiding as authorization.
- Do not treat caller-supplied ids as authorization proof.

## Dependencies and related tasks
- `0143_shared_gateway_per_principal_runtime_router.md`
- `0145_gateway_admin_console_bootstrap.md`
- `0153_gateway_browser_session_security_contract.md`
- `0148_gateway_workflow_registry_acl.md`
- `0151_runtime_explorer_contract.md`

## Expected outcomes
- A non-admin cannot call admin-only route families.
- A user cannot read or mutate another user's runtime by guessing ids.
- Discovery can report permission-aware action availability.

## Validation
- Alice/Bob route-family isolation tests across users, runs, ledgers,
  artifacts, memory, workflows, prompt cache, workspace files, and admin routes.
- Dev read-bypass tests proving admin user lists and sensitive data remain
  protected.
- Contract tests for permission metadata.

## Recent validation
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_security_middleware_unit.py -q` -> 31 passed.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py::test_gateway_user_runtime_ids_are_unique_per_tenant abstractgateway/tests/test_gateway_principal_isolation_matrix.py -q` -> 2 passed.
- `python -m py_compile abstractgateway/src/abstractgateway/users.py abstractgateway/src/abstractgateway/routes/gateway.py` -> passed.
- `python -m pytest abstractgateway/tests/test_gateway_security_middleware_unit.py abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_console.py abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py -q` -> 51 passed, 2 warnings.
- `python -m compileall -q abstractgateway/src/abstractgateway abstractflow/web/backend` -> passed.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_security_middleware_unit.py abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py` -> 44 passed.
- `python -m pytest abstractgateway/tests` -> 261 passed, 2 skipped.
- `python -m pytest abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py` -> 20 passed.
- `python -m pytest abstractgateway/tests/test_gateway_install_profiles.py abstractgateway/tests/test_gateway_capability_catalog_proxy.py` -> 29 passed.
- `python -m compileall -q abstractgateway/src/abstractgateway` -> passed.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_principal_isolation_matrix.py abstractgateway/tests/test_capabilities_endpoint_contract.py abstractgateway/tests/test_abstractflow_editor_gateway_contract.py -q` -> 26 passed.
- `python -m py_compile abstractgateway/src/abstractgateway/routes/gateway.py abstractgateway/src/abstractgateway/security/sessions.py abstractgateway/src/abstractgateway/security/gateway_security.py` -> passed.

## Progress checklist
- [ ] Write route-family policy matrix.
- [x] Add central authorization helper.
- [x] Harden dev read bypass for admin/operator route families.
- [x] Add first hosted route-family policy table in Gateway middleware.
- [x] Admin-gate server-workspace and operator route families.
- [x] Add runtime-id uniqueness and retained-runtime reservation guards for
  tenant-local Gateway users.
- [x] Add admin-only retained runtime list/transfer/purge routes.
- [x] Add initial Alice/Bob isolation tests for runs, ledgers, and artifacts.
- [x] Extend Alice/Bob matrix to KG/session memory, private workflows,
  prompt-cache key naming, session artifacts, and defaults overlays.
- [x] Prove regular users cannot use admin-only workspace helper/import/export
  surfaces.
- [x] Add machine-readable denial tests for first operator route families.
- [x] Add discovery leak tests for admin-only workspace artifact and
  prompt-cache provider-control availability.
- [x] Update docs with current route-family boundaries.

## Guidance for the implementing agent
Add authorization at the lowest shared Gateway layer available. Avoid scattering
ad hoc `if admin` checks without a policy table.

## Implementation note - 2026-05-30

This item is materially advanced but not fully closed. The current code now has
a central policy table and tested denials for operator/server-workspace route
families. The remaining closure criterion is the broader Alice/Bob isolation
matrix and discovery leak tests across every user-owned route family.

The latest security pass adds table-driven denial coverage for admin, audit,
process, backlog, triage, report, email, host, model residency, workspace,
bloc, and prompt-cache route families using a non-admin user with wildcard
scopes. This proves broad scopes cannot bypass `admin_required=True`; it does
not replace the remaining user-owned data-plane isolation matrix.

The latest isolation pass adds runtime-id uniqueness enforcement and extends
the cross-user matrix to run, ledger, artifact, session artifact, KG/session
memory, private workflow bundle, VisualFlow draft, prompt-cache naming, and
capability-default overlay surfaces. It also verifies that ordinary users see
admin-only workspace artifact import/export and provider prompt-cache controls
as unavailable in discovery, and that direct workspace helper/import calls
return machine-readable `403` denials.

This item should remain open only for future route families as they are added
or promoted. The user-requested Alice/Bob matrix extension is complete.

--- docs/backlog/planned/gateway-control-plane/0147_gateway_per_principal_config_secrets_defaults.md ---
# Planned: Gateway per-principal config, secrets, and defaults

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0033, ADR-0035
- ADR impact: May revise existing ADR

## Context
Provider/model defaults and API keys are currently configured through Core
local config, environment variables, or duplicated app UI settings. Gateway is
becoming the hosted control-plane UX, but Core should remain the schema and
persistence authority for capability defaults and provider credentials.

## Current code reality
- ADR-0035 states Core owns capability default schema and persistence, while
  Gateway is the control-plane access layer.
- AbstractCore has config primitives for default models, provider API keys,
  base URLs, and capability route defaults.
- Flow mostly supports `Auto` and Gateway-discovered defaults.
- Code and Observer still have app-local settings/auth/defaults that do not yet
  fully match the Gateway browser-session model.
- Gateway now supports per-principal capability-default overlays in hosted
  user-auth mode. Writes to `/api/gateway/config/capability-defaults/...` are
  stored under the caller's runtime data plane as
  `config/capability_defaults.json` and merged over execution-host Core
  defaults for Gateway responses.
- The admin/root data plane overlay now acts as the Gateway baseline. Normal
  users inherit that Gateway baseline first, then apply their own per-user
  overlay. User overrides do not mutate the Gateway baseline or other users'
  defaults.
- Gateway Console v0 exposes those per-principal defaults.
- Gateway provider endpoint profiles now cover the first explicit
  per-principal/gateway-scoped provider-secret injection path for reusable
  virtual providers such as `endpoint:office-vllm`; broader secret vault,
  encryption, bridge, and delegated-tool rules remain open.

## Problem
Users must configure provider/model defaults repeatedly across apps, and hosted
users need their own API keys/defaults isolated from other users. Storing keys
in browser localStorage or mutating global env is wrong for multi-user Gateway
deployments.

## What we want to do
Expose Gateway APIs and UI for per-principal provider credentials, base URLs,
and capability defaults, while delegating schema/persistence mechanics to Core
or per-principal Core config. Apps should consume Gateway defaults and only ask
for provider/model when a user intentionally pins an override.

## Why
This removes duplicated UX, aligns apps behind Gateway, and preserves user
isolation for secrets and model choices.

## Requirements
- Default resolution is preference selection within policy ceilings:
  operator/tenant allowlist and capability policy constrain request overrides,
  workflow pins, user defaults, tenant defaults, gateway defaults, and
  execution-host Core defaults.
- Resolved provider/model metadata reports non-secret provenance so UIs can show
  whether a value came from request, workflow, user, tenant, Gateway baseline,
  or Core.
- Explicit workflow pins remain reproducible unless denied by current host
  policy, in which case denial is explicit rather than silently rerouted.
- API keys and provider secrets are never stored in browser storage.
- Per-user secrets are injected only into that user's runtime context.
- Capability defaults must not expose secret values.
- Gateway Console can collect keys/defaults but must not become a second
  defaults owner independent of Core.
- Before implementation, record the Core/Gateway storage boundary: who encrypts
  secrets, who can read raw values, how rotation/deletion works, how backups are
  handled, and how access is audited.
- Secrets must be redacted from logs, ledgers, artifacts, tool traces, audit
  payloads, and discovery responses.
- Define propagation rules for subruns, bridges, delegated tools, and any
  admin/system execution path before those paths can use per-principal secrets.

## Suggested implementation
Add Gateway config endpoints that wrap Core config/default APIs for the current
principal. First decide whether the implementation uses a per-principal secret
store, per-principal Core config root, or another Core-owned mechanism. Expose
readiness checks and catalog previews in Gateway Console only after that
boundary is explicit.

## Scope
- Gateway APIs for provider credentials and capability defaults.
- Gateway Console config page.
- Per-principal isolation tests for secrets/defaults.
- App docs that point users to Gateway defaults.

## Non-goals
- Do not remove direct AbstractCore CLI/config for local developer usage.
- Do not force every app to remove explicit provider/model overrides.
- Do not store raw secrets in Gateway audit logs or browser storage.

## Dependencies and related tasks
- ADR-0035 and `docs/guide/capability-routing-defaults.md`.
- `0145_gateway_admin_console_bootstrap.md`
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0153_gateway_browser_session_security_contract.md`
- `../../completed/0149_cross_app_gateway_auth_defaults_convergence.md`

## Expected outcomes
- A Gateway user can configure provider keys/defaults once and use them from
  Flow, Code, Observer, Assistant, and bridges.
- Alice's provider keys/defaults are not visible or usable by Bob.
- Apps default to Gateway/Core defaults unless a run/workflow explicitly pins.

## Validation
- Alice/Bob secret isolation tests.
- Default cascade tests.
- UI tests proving secrets are write-only or masked after creation.
- App smoke tests with blank provider/model resolving through Gateway defaults.

## Recent validation
- `python -m pytest abstractgateway/tests/test_gateway_security_middleware_unit.py abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_console.py abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py -q` -> 51 passed, 2 warnings.
- `python -m compileall -q abstractgateway/src/abstractgateway abstractflow/web/backend` -> passed.
- `python -m pytest abstractgateway/tests` -> 261 passed, 2 skipped.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_security_middleware_unit.py abstractgateway/tests/test_gateway_console.py` -> 29 passed.
- `python -m pytest abstractgateway/tests/test_gateway_install_profiles.py abstractgateway/tests/test_gateway_capability_catalog_proxy.py` -> 29 passed.

## Progress checklist
- [x] Define initial per-principal capability-default storage boundary with
      Core schema and Gateway per-principal access control.
- [x] Define and implement the initial provider endpoint profile injection
      boundary for Gateway-owned virtual providers.
- [ ] Define provider-secret encryption/rotation/audit boundary beyond the
      initial local JSON store.
- [x] Define initial provenance behavior for Gateway and per-principal defaults
      (`source=abstractgateway.gateway` and `source=abstractgateway.principal`).
- [ ] Define runtime/subrun/bridge secret injection rules.
- [x] Add Gateway APIs for per-principal capability-default overlays.
- [x] Add Gateway Console config UX for per-principal defaults.
- [x] Update app/framework docs for current defaults behavior.
- [x] Add Alice/Bob default isolation tests.
- [x] Add initial endpoint profile secret redaction and non-admin scope tests.
- [ ] Add broader secret isolation tests after a complete vault/bridge boundary exists.

## Implementation note - 2026-05-30

This item is partially implemented for provider/model/base URL defaults.
Gateway provider endpoint profiles now provide the first raw provider credential
path without writing user secrets into browser storage, workflow JSON, or
process-wide environment variables. Profiles are resolved per request into
transient Runtime parameters and redacted from persisted Runtime observability.
The remaining design work is a fuller Core/Gateway secret contract covering
encryption at rest, rotation semantics, subruns, bridges, delegated tools,
audit, and deletion.

Default cascade as implemented today: execution-host Core defaults provide the
base route set, the Gateway/root overlay provides the operator baseline, and
the current user's runtime overlay wins only for that user. Workflow pins and
per-request overrides still need to be resolved by run-start policy in later
items; do not silently reroute explicit workflow pins without an explicit
policy denial or override record.

## Guidance for the implementing agent
Keep the authority split crisp: Core owns config schema and low-level execution
config; Gateway owns authenticated hosted UX and per-principal access control.

--- docs/backlog/planned/gateway-control-plane/0148_gateway_workflow_registry_acl.md ---
# Planned: Gateway workflow registry ACLs

## Metadata
- Created: 2026-05-30
- Status: In progress
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: Needs new ADR or ADR revision

## Context
Flow authors VisualFlows and publishes bundles through Gateway. Runtime treats
workflow bundles as transport/execution artifacts and intentionally does not
own trust policy. Gateway must decide who can import, publish, run, promote,
deprecate, remove, or grant access to workflows.

## Current code reality
- Gateway has per-principal service routing and per-user flow/bundle storage.
- Gateway VisualFlow CRUD, publish, bundle upload/remove/deprecate endpoints
  exist but need clearer admin/user/catalog permission semantics.
- Flow currently consumes Gateway capability/discovery metadata and can hide or
  show actions, but server-side Gateway must enforce permissions.
- Existing per-principal `/visualflows` and bundle directories are private
  authoring/storage surfaces. A shared tenant/framework catalog should be an
  explicit Gateway-level metadata store, not an accidental reuse of one user's
  bundle directory.

## Problem
Workflow registration and permissions are not yet a clean control-plane model.
A globally visible workflow must not imply shared runtime state or unchecked
write/tool permissions. Users should be able to draft private workflows, while
admins control tenant/framework catalogs.

## What we want to do
Implement a two-tier Gateway workflow registry:
- private/user registry for drafts and user-owned workflows;
- tenant/framework catalog for admin-promoted immutable bundle versions with
  explicit ACLs and run policies.

Registry scopes should be explicit (`private`, `tenant_catalog`,
`framework_catalog`, and later `system`) so a `bundle_id` collision or guessed
id cannot silently switch between private and shared authority.

## Why
This lets Flow remain an authoring tool while Gateway becomes the trusted
workflow registry and permission authority.

## Requirements
- Non-admin users can draft/test private workflows in their own runtime.
- Admins can import/register/promote/deprecate/remove tenant/framework catalog
  bundles.
- Global/catalog workflows execute in the requesting user's runtime unless
  explicitly launched as admin/system workflows.
- ACL metadata lives in Gateway, not inside trusted bundle manifest fields.
- Workspace/tool/write permissions are intersected with user role, workflow ACL,
  tenant policy, and operator workspace policy.
- Effective run policy is materialized at run start and includes `run_as`,
  workflow visibility, allowed tools, workspace grants, secret access, approval
  mode, network/process permissions, and destructive-action permissions.
- Enforcement happens both at run start and at later tool/workspace/secret
  access points; a workflow allowed to start is not automatically allowed to
  perform every side effect it requests.
- Admin/system workflow launch semantics require explicit service-principal
  rules, approval gates, workspace binding, secret-source rules, and audit logs
  before they are enabled.
- Discovery exposes permission-aware action metadata for Flow UX.
- Existing workflows that depend on an older catalog workflow version keep
  running against that immutable version unless the version is explicitly
  blocked for safety. Updating a default workflow pointer must not rewrite
  historical bundle references or private workflows built on top of a previous
  version.

## Suggested implementation
Add catalog metadata records keyed by bundle id, version, sha256, status,
visibility, owner, publisher, promoter, timestamps, and ACL. Include review
status, checksum verification, and the immutable policy snapshot or policy
version used at run start. Keep bundle content immutable by version; updates
create new versions and optional default-pointer changes. Add run-start,
scheduled-run, subworkflow, and per-action checks that resolve catalog ACL and
effective run policy before execution.

Recommended state machine:
`private/draft -> submitted -> approved/published -> deprecated -> removed/tombstoned`.
Deprecation blocks new starts but preserves history/replay. Removal should keep
tombstones so dependent workflows can explain why a referenced version is no
longer startable.

## Scope
- Gateway registry metadata and ACL APIs.
- Run-start authorization for catalog/private workflows.
- Flow discovery contract updates for allowed/denied actions.
- Tests for private vs catalog workflows.
- Migration compatibility for existing private `/visualflows` and user bundle
  storage.

## Non-goals
- Do not make Runtime own ACL policy.
- Do not trust bundle-declared permissions without Gateway grants.
- Do not add a full marketplace UX in this item.
- Do not change `/bundles` from "current runtime bundles" to "global catalog"
  without an explicit scope or a separate catalog endpoint.

## Dependencies and related tasks
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0145_gateway_admin_console_bootstrap.md`
- `0153_gateway_browser_session_security_contract.md` for browser-admin
  interactions with registry controls.
- Flow publish/import UI.
- Runtime workflow bundle validation.

## Expected outcomes
- Users cannot run or mutate workflows by guessing bundle ids.
- Admins can promote workflows to a tenant/framework catalog.
- Catalog workflows run in the caller's data plane by default.
- Deprecation blocks new starts while preserving historical replay.

## Validation
- Alice/Bob private workflow isolation tests.
- Non-admin publish-to-catalog denial tests.
- Catalog ACL start/deny tests.
- Immutable bundle version/sha256 tests.
- Default-pointer update tests proving existing version references are not
  rewritten.
- Scheduled-run and subworkflow policy inheritance tests.
- Workspace policy enforcement tests.

## Progress checklist
- [x] Define registry tiers and metadata schema.
- [ ] Define effective run policy and admin/system workflow semantics.
- [x] Add catalog ACL APIs.
- [x] Enforce run-start ACL/policy.
- [x] Enforce scheduled-run and catalog subworkflow status/policy checks.
- [ ] Enforce per-tool/per-workspace policy checks.
- [x] Update Gateway discovery metadata for catalog/private action split.
- [x] Add two-user tests.

## Implementation note - 2026-05-30

Implemented the first catalog-control slice in `abstractgateway`:

- Added a Gateway-owned workflow catalog store under the root Gateway data dir.
  Catalog bundle bytes are immutable by `scope + tenant + bundle_id +
  bundle_version + sha256`; re-uploading the same version with different bytes
  is rejected.
- Added explicit catalog endpoints:
  - user-visible `GET /api/gateway/workflow-catalog`;
  - admin-only upload, promote, default pointer, ACL, deprecate, block, and
    tombstone routes under `/api/gateway/admin/workflow-catalog`.
- Kept private `/api/gateway/visualflows` and `/api/gateway/bundles` as
  per-principal runtime authoring/storage surfaces.
- Loaded tenant catalog bundles into each user's runtime host under internal
  catalog bundle ids so private bundle ids cannot shadow catalog ids.
- Added `registry_scope` to run start and scheduled run requests. Catalog
  starts resolve through ACLs and the admin default pointer, then run in the
  requesting user's runtime.
- Added host-side guards so direct internal catalog starts require a
  Gateway-issued signed workflow-policy snapshot, and catalog subworkflow
  starts are blocked when the signature, runtime binding, ACL, content hash, or
  catalog status no longer validates.
- Made catalog scope explicit: omitted `registry_scope` stays on the private
  runtime bundle surface and does not silently fall through to the shared
  catalog.
- Blocked direct private-bundle inspection of catalog-internal bundle ids and
  added ACL-aware catalog flow/schema inspection routes.
- Reworked catalog install so byte immutability and metadata updates are
  checked in one critical section; same-content inactive re-uploads cannot move
  the default pointer back to an inactive version.
- Rejected `framework_catalog` at the API until cross-tenant host loading and
  policy semantics are implemented.
- Added discovery metadata so clients can distinguish private bundle actions
  from catalog/admin actions.

Validation:

- `python -m py_compile abstractgateway/src/abstractgateway/workflow_catalog.py abstractgateway/src/abstractgateway/config.py abstractgateway/src/abstractgateway/service.py abstractgateway/src/abstractgateway/hosts/bundle_host.py abstractgateway/src/abstractgateway/routes/gateway.py abstractgateway/tests/test_gateway_workflow_catalog_acl.py`
- `python -m pytest abstractgateway/tests/test_gateway_workflow_catalog_acl.py -q` -> `2 passed`
- `python -m pytest abstractgateway/tests/test_gateway_workflow_catalog_acl.py abstractgateway/tests/test_gateway_workflow_deprecation.py abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_capabilities_endpoint_contract.py abstractgateway/tests/test_abstractflow_editor_gateway_contract.py -q`
- `python -m pytest abstractgateway/tests -q` -> `265 passed, 2 skipped`

Remaining work:

- Define any future admin/system run mode separately; current catalog runs are
  caller-runtime only.
- Intersect workflow catalog policy with tool, workspace, secret, network, and
  destructive-action policies at effect/action boundaries.
- Build Flow/Gateway Console UX for catalog promotion, default movement, ACLs,
  and version status operations.

## Refinement note - 2026-05-30

Admin install/update/remove of default workflows should be modeled as catalog
version management, not file replacement. Admins can promote a new immutable
bundle version and move a default pointer, but private workflows and historical
runs must retain their exact version reference. A later admin/system workflow
execution mode must be explicit and audited; the default for catalog workflows
is still "run in the requesting user's runtime."

## Guidance for the implementing agent
Keep authoring and authority separate: Flow may request publication, but Gateway
must decide and audit the permission result.

--- docs/backlog/completed/0149_cross_app_gateway_auth_defaults_convergence.md ---
# Completed: Cross-app Gateway auth and defaults convergence

## Metadata
- Created: 2026-05-30
- Status: Completed
- Completed: 2026-05-30

## ADR status
- Governing ADRs: ADR-0018, ADR-0033, ADR-0035
- ADR impact: No ADR change in this pass; the convergence behavior is covered
  by the existing Gateway/control-plane/defaults ADRs and the browser-session
  contract tracked in `0153`.

## Context
AbstractFlow now uses browser-session Gateway user auth. Other apps still have
older or duplicated auth/default patterns. Code, Observer, Assistant, and any
browser UI should converge on the same Gateway session and default-resolution
model.

## Current code reality
- Flow uses Gateway URL + user + token only during sign-in; it exchanges the
  user token for a Gateway browser session and stores only the opaque session id
  in an HTTP-only browser cookie.
- Flow mutating Gateway proxy calls carry a CSRF token, and Gateway validates it
  for session-authenticated writes.
- Code Web now supports the same hosted Gateway URL + user + token sign-in
  shape. Its static server creates an app-scoped browser session by exchanging
  the user token with Gateway server-side, stores no bearer token in
  localStorage, proxies `/api/*` with `X-AbstractGateway-Session`, and requires
  an app CSRF header for mutating calls.
- Observer now has the same hosted browser-session path and no longer persists
  Gateway bearer tokens in localStorage. Its direct bearer mode remains a local
  development escape hatch.
- Flow static/Vite-hosted session login now consumes Gateway's cookie-based
  login response correctly; it no longer assumes the Gateway session id and
  CSRF token are returned in JSON.
- Code Web start flow no longer blocks when provider/model are blank; hosted
  runs can rely on Gateway/Core defaults unless the user sets an explicit
  override.
- Observer and Code Web still have app-specific UI copy and settings layouts;
  a shared auth/default component remains optional if duplication grows.

## Problem
Users must learn different auth/default models for each app. Duplicated
provider/model/default UI causes drift and can defeat per-user isolation.

## What we want to do
Move every hosted app to Gateway user-session auth and Gateway/Core defaults.
Apps should expose provider/model only as explicit per-run, per-workflow, or
advanced overrides.

## Why
This improves security, reduces duplicated UI, and makes Gateway the consistent
deployment control plane.

## Requirements
- Flow, Code, Observer, Assistant, and future browser apps use Gateway
  user-session auth in hosted mode.
- No hosted browser app stores bearer tokens in localStorage.
- Hosted mode detection and session semantics come from
  `0153_gateway_browser_session_security_contract.md`; local/offline app modes
  remain allowed to keep local development ergonomics.
- Apps use Gateway catalogs/defaults by default.
- Provider/model pins remain available where they are natural task-specific
  overrides.
- Disconnect/sign-out clears only the browser session for that app/domain.

## Per-app hosted/local behavior matrix

This matrix is the concrete meaning of "cross-app convergence": each app keeps
its natural local ergonomics, but hosted browser surfaces share the Gateway
session/default model.

| App/surface | Hosted auth behavior | Local/development behavior | Default provider/model behavior | Notes |
|---|---|---|---|---|
| AbstractFlow web | User enters Gateway URL, user id, and user token once. The host exchanges the token for a Gateway browser session and proxies Gateway calls with session + CSRF. | Local script can print a dev user/token and start Flow/Gateway together. No ambient admin login should appear in the browser. | Nodes default to Gateway/Core capability defaults unless the flow pins provider/model. | Reference browser UX for Gateway sign-in. |
| AbstractCode Web | Hosted server exchanges Gateway user credentials server-side, stores only app-scoped session cookies, strips bearer tokens from saved browser settings, and proxies `/api/*`. | CLI/env bearer token remains acceptable for trusted local runs. | Blank provider/model means "use Gateway defaults"; explicit per-run overrides remain allowed. | No localStorage bearer token in hosted mode. |
| AbstractObserver web | Hosted server follows the same app-scoped session proxy and token-storage stripping as Code Web. | Direct bearer-token mode remains a local/operator escape hatch. | Observer should read Gateway catalogs/defaults for display and filters, not own global model defaults. | Observer remains observability UX, not the admin setup surface. |
| Gateway Console | Native Gateway browser-session app. Users sign in with user id + token; admins manage users and Gateway baselines; normal users manage their own overlays. | Same URL works locally; dev scripts print the admin/user credential to enter. | Admin/default runtime owns Gateway baseline; user runtime owns per-user overlay. Provider/model selectors must be discovery-driven. | Console is account/admin/config, not deep runtime exploration. |
| AbstractAssistant desktop | Not a hosted browser app today. It can keep CLI/env token or stored local config for trusted desktop use. | Same as hosted until a browser Assistant exists. | Gateway mode should prefer Gateway/Core defaults and only send explicit overrides when the user chooses them. | Do not force browser-cookie auth onto terminal/desktop-only surfaces. |
| Scripts/automation | Use bearer tokens or admin/user tokens directly as server-to-server credentials. | Same. | Prefer Gateway defaults unless a reproducible run needs explicit provider/model. | Automation is not browser storage; protect tokens with OS/process controls. |

Shared auth/default UI extraction is intentionally deferred. The current
duplication is understandable and app-specific enough that a shared component
could harden the wrong abstraction too early. Extract a shared component only
after two or more browser apps need the same fields, validation, cookie-status
display, logout behavior, and defaults picker with no app-specific branching.

## Design review tensions

The useful disagreement in this item is not "should apps converge" versus "do
nothing"; it is where convergence should stop.

- Centralized hosted auth/defaults vs app-local ergonomics: hosted browser apps
  should share the Gateway browser-session and Gateway/Core defaults model, but
  desktop, CLI, and trusted local development flows should keep direct token
  ergonomics. Forcing cookie auth onto every client would make automation and
  local development worse without improving hosted browser safety.
- Shared component now vs delayed extraction: a common sign-in/defaults
  component would reduce visual drift, but the apps still have different
  layouts, status affordances, and local modes. Extracting now would likely
  encode the wrong abstraction. The threshold is repeated identical behavior,
  not the existence of similar fields.
- Gateway baseline defaults vs per-user overrides: Gateway should provide the
  tenant/admin baseline so apps stop duplicating global provider/model
  configuration. Per-user overlays remain a separate `0147` concern so one
  user's defaults do not silently change everyone else's behavior.
- Gateway Console vs Observer or a future Manager/Explorer: account, admin,
  auth, and baseline configuration belong in the Gateway Console. Observer
  should stay focused on runs and platform observability. Runtime exploration is
  intentionally separate until `0151` proves the contract and UX pressure.
- Browser security vs operator escape hatches: hosted browser mode must not
  persist bearer tokens in localStorage. Server-to-server scripts and local
  operator tools can still use tokens directly, but docs and startup scripts
  must label that as trusted-local or automation behavior.

## Suggested implementation
Audit each app. Introduce shared session/auth helpers or a small common UI kit
component if duplication becomes high. Migrate app docs and settings screens to
Gateway defaults.

## Scope
- App auth/session flows.
- App provider/model default UX.
- Docs and tests.

## Non-goals
- Do not remove local/offline app modes.
- Do not remove explicit provider/model overrides needed for reproducibility.
- Do not make Observer the admin setup UI.

## Dependencies and related tasks
- `0147_gateway_per_principal_config_secrets_defaults.md`
- `0145_gateway_admin_console_bootstrap.md`
- `0153_gateway_browser_session_security_contract.md`
- `0150_observer_manager_responsibility_split.md`

## Expected outcomes
- A Gateway user can sign in consistently across apps.
- Apps default to Gateway/Core configuration without duplicating global default
  settings.
- Hosted app auth no longer relies on app-local admin/server tokens.

## Validation
- Per-app login/logout tests.
- Token storage audit proving no localStorage bearer token in hosted mode.
- Blank provider/model smoke tests resolving through Gateway defaults.
- Cross-app Alice/Bob isolation smoke tests.

## Progress checklist
- [x] Audit Code Web auth/default storage.
- [x] Audit Observer auth/default storage.
- [x] Audit Assistant Gateway mode auth/defaults.
- [x] Migrate Code Web hosted mode to Gateway browser-session proxy auth.
- [x] Migrate Observer hosted mode to Gateway browser-session proxy auth.
- [x] Fix Flow static/Vite session login to parse Gateway login cookies.
- [x] Define per-app hosted/local auth/default behavior matrix.
- [x] Decide whether to extract shared auth/default UX now. Result: defer; the
  current app-specific duplication is acceptable and a shared component should
  wait until two or more apps need the same fields, validation, status display,
  logout behavior, and defaults picker without app-specific branching.
- [x] Add initial token-storage and hosted proxy smoke tests.
- [x] Update package and framework docs/tests for the current convergence
  behavior.

## Recent audit notes
- Code Web and Observer now store only app-scoped browser-session cookies in
  hosted mode. Their settings persistence explicitly strips `auth_token`, and
  their packaged servers reject browser-supplied Gateway URL changes on
  non-local hosted UI hostnames unless an explicit app override is enabled.
- Assistant remains a local/desktop client and can keep CLI/env bearer-token
  ergonomics until a hosted browser surface exists.
- Flow is the reference implementation for the current browser session contract.

## Recent validation
- `npm test -- --run src/lib/storage.test.ts` in `abstractcode/web` -> 1 passed.
- `npm test -- --run src/ui/auth_storage.test.ts` in `abstractobserver` -> 1 passed.
- `npm run build` in `abstractcode/web` -> passed.
- `npm run build` in `abstractobserver` -> passed.
- `npm run build` in `abstractflow/web/frontend` -> passed.
- `node --check abstractcode/web/bin/cli.js && node --check abstractobserver/bin/cli.js && node --check abstractflow/web/frontend/bin/cli.js` -> passed.
- Stub-Gateway hosted-session proxy smoke tests for AbstractCode Web,
  AbstractObserver, and AbstractFlow static server -> passed. The smoke tests
  verified cookie-based login exchange, no token leakage into app cookies,
  Gateway session/CSRF injection, browser cookie stripping, Authorization
  stripping, and app CSRF enforcement for mutating proxied calls.
- `python -m pytest abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py -q` -> 21 passed, 2 warnings.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_principal_isolation_matrix.py abstractgateway/tests/test_capabilities_endpoint_contract.py abstractgateway/tests/test_abstractflow_editor_gateway_contract.py -q` -> 26 passed.

## Guidance for the implementing agent
Preserve task-specific app ergonomics. The goal is not to make all apps look the
same, but to make identity, defaults, and secrets consistent.

## Completion report

Date: 2026-05-30

Summary:
- Documented the concrete per-app hosted/local auth/default behavior matrix for
  AbstractFlow Web, AbstractCode Web, AbstractObserver Web, Gateway Console,
  AbstractAssistant desktop, and scripts/automation.
- Confirmed the shared auth/default component should not be extracted yet. The
  right criterion is repeated identical behavior across multiple browser apps,
  not a desire for visual uniformity.
- Verified the current hosted browser apps use Gateway browser-session proxy
  auth and do not persist Gateway bearer tokens in browser settings.
- Repaired one stale AbstractFlow CLI doc sentence so it now says Flow stores
  the opaque Gateway session id, not the user token.

Files or symbols touched:
- `docs/backlog/completed/0149_cross_app_gateway_auth_defaults_convergence.md`
- `docs/backlog/overview.md`
- `docs/backlog/planned/gateway-control-plane/README.md`
- `docs/backlog/planned/gateway-control-plane/0147_gateway_per_principal_config_secrets_defaults.md`
- `docs/backlog/planned/gateway-control-plane/0153_gateway_browser_session_security_contract.md`
- `docs/guide/gateway-security.md`
- `llms.txt`, `llms-full.txt`
- `abstractflow/docs/cli.md`

Validation:
- `rg` audit across AbstractFlow, AbstractCode Web, AbstractObserver, and root
  docs for hosted auth/default/token-storage wording.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_principal_isolation_matrix.py abstractgateway/tests/test_capabilities_endpoint_contract.py abstractgateway/tests/test_abstractflow_editor_gateway_contract.py -q` -> 26 passed.
- `python -m py_compile abstractgateway/src/abstractgateway/routes/gateway.py abstractgateway/src/abstractgateway/security/sessions.py abstractgateway/src/abstractgateway/security/gateway_security.py` -> passed.
- `python /Users/albou/.codex/skills/.system/skill-creator/scripts/quick_validate.py /Users/albou/.codex/skills/architect` -> passed.
- `python /Users/albou/.codex/skills/.system/skill-creator/scripts/quick_validate.py /Users/albou/.codex/skills/review` -> passed.

Behavior changes:
- No runtime behavior change is introduced by completing this item. The
  behavior had already landed in Flow, Code Web, Observer, Gateway session
  routing, and Gateway defaults. This completion closes the planning item by
  making the behavior matrix, deferral decision, docs state, and validation
  explicit.

Residual risks:
- Direct bearer-token mode remains available for local/operator development in
  Code Web and Observer. This is intentional, but hosted docs must continue to
  steer users toward browser-session proxy auth.
- AbstractAssistant is still a local/desktop client. If a hosted browser
  Assistant appears, it should implement the same Gateway browser-session
  contract rather than reusing desktop token storage.
- A shared auth/default component should be revisited only when duplicate app
  implementation creates proven drift or maintenance cost.

Follow-ups:
- Keep `0153` open as the durable session/cookie contract while new browser
  apps are added.
- Keep `0147` open for provider-secret storage/injection boundaries; `0149`
  does not solve per-user provider credentials.
- See proposed item `0155` before extracting a shared hosted proxy helper; the
  current posture is package-local code plus conformance tests.

--- docs/backlog/planned/gateway-control-plane/0150_observer_manager_responsibility_split.md ---
# Planned: Observer and Manager responsibility split

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: May revise existing ADR

## Context
Observer is useful but broad. It has grown toward observability, launch,
backlog, email, process, and operational pages. Gateway now needs account,
admin, config, user/runtime, and workflow-permission UX. Putting all of that
into Observer would make app boundaries unclear.

## Current code reality
- Observer is the existing runtime/run observability app.
- Gateway has control-plane APIs and is gaining identity/routing authority.
- There is no dedicated Manager/Admin app yet.
- Gateway Console v0 is planned as a narrow built-in control-plane UX.

## Problem
Without a responsibility split, Observer can become a catch-all operational app
and Gateway can become a monolithic UI. Users need a clearer product map.

## What we want to do
Define app responsibilities early enough to contain scope before Gateway
Console, Runtime Explorer, and cross-app migrations expand. Proposed ownership:
- Gateway/Gateway Console: identity, account, admin, config, runtime summary,
  workflow registry permissions.
- Observer: run/ledger/artifact observability, runtime health, audit views, and
  operational monitoring.
- Flow: workflow authoring.
- Code: coding-agent UX.
- Assistant: personal assistant UX.
- Future Explorer/Manager: only if Gateway Console or Observer becomes too broad.

## Why
Clear product boundaries improve user onboarding, code ownership, security, and
release planning.

## Requirements
- Audit Observer high-trust surfaces: backlog execution, email, process control,
  env management, scheduling, broad runtime management.
- Immediately classify existing high-trust surfaces as observability,
  admin/config, operator-only, domain-app, or migration candidate.
- Hosted-mode unsafe paths must be marked operator-only behind Gateway
  authorization or hidden/disabled until `0146` enforcement exists.
- Decide which surfaces remain Observer operator views and which move behind
  Gateway Console/Manager APIs.
- Define links between apps instead of duplicating full functionality.
- Keep all sensitive operations authorized by Gateway, not by frontend routing.

## Suggested implementation
Write a short app-boundary decision doc or ADR update, then migrate one surface
at a time. Start by documenting which current Observer pages are observability,
which are admin/config, and which are domain apps.

## Scope
- App responsibility audit.
- Docs/ADR update.
- Containment notes for high-trust Observer/Gateway routes that should not be
  presented as ordinary hosted-user UX.
- Follow-up tickets for migrations.

## Non-goals
- Do not create a new package before the boundary is proven.
- Do not remove useful Observer pages without replacement.
- Do not move Flow authoring into Gateway.

## Dependencies and related tasks
- `0145_gateway_admin_console_bootstrap.md`
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0151_runtime_explorer_contract.md`
- `0152_abstractmanager_package_extraction.md`

## Expected outcomes
- Users can understand which app to open for admin/config vs observability vs
  authoring.
- High-trust Observer surfaces are either clearly operator-only or moved into
  Gateway-managed control plane.
- Future package split decisions are grounded in actual use, not naming alone.

## Validation
- Documentation names each app's responsibility and non-goals.
- UI navigation links users to the right app/surface.
- Authorization tests protect high-trust surfaces.

## Progress checklist
- [ ] Audit Observer surfaces.
- [ ] Draft app responsibility matrix.
- [ ] Classify high-trust surfaces and containment status.
- [ ] Update ADR/docs.
- [ ] Create migration backlog items where needed.

## Guidance for the implementing agent
Do not solve this by naming a new app too early. First make the ownership model
explicit, then extract only when code and UX pressure justify it.

--- docs/backlog/planned/gateway-control-plane/0153_gateway_browser_session_security_contract.md ---
# Planned: Gateway browser session security contract

## Metadata
- Created: 2026-05-30
- Status: Planned
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: Needs new ADR or ADR revision

## Context
Flow already uses browser-session Gateway auth, and the Gateway Console plus
other hosted apps need the same security model. Gateway user tokens are bearer
credentials assigned to a principal. Browser sessions are app-facing sessions
that should be shorter-lived, revocable, and scoped to the browser/app origin.

## Current code reality
- Gateway exposes `/api/gateway/session/login` and
  `/api/gateway/session/logout` for registry-backed user browser sessions.
- Flow accepts Gateway URL, user id, and user token at connection time, validates
  the token, exchanges it for an opaque Gateway browser session, and stores only
  the session id in an HTTP-only Flow cookie across the Python host, Node static
  host, and Vite dev proxy.
- Flow stores a CSRF token in a separate browser cookie and sends it as
  `X-AbstractFlow-CSRF`; the Flow proxy forwards `X-AbstractGateway-Session`
  and `X-AbstractGateway-CSRF` to Gateway for mutating requests.
- Gateway invalidates browser sessions when the backing user is disabled,
  deleted, or its token hash changes.
- Gateway session cookies are HTTP-only for the session id and readable only for
  the CSRF token. They use `SameSite=Lax`, path `/`, no `Secure` flag on plain
  HTTP, and `Secure` when the request scheme or trusted proxy header is HTTPS.
  Non-remembered sessions omit `Max-Age`; remembered sessions set `Max-Age`.
- Gateway user records store hashed bearer tokens and return generated/rotated
  tokens only once.
- Code Web and Observer now follow the same hosted-session proxy contract in
  their packaged Node servers: Gateway user credentials are exchanged
  server-side, app-scoped session cookies are issued, `/api/*` is proxied with
  `X-AbstractGateway-Session`, writes require app CSRF headers, and saved
  browser settings strip bearer tokens. They now also reject browser-supplied
  Gateway URL changes on non-local hosted UI hostnames unless an explicit
  app-specific override is enabled. Host checks trust the request `Host` header
  by default; forwarded host headers require an explicit trust-proxy env setting.
- Assistant remains a local/desktop app and can keep its CLI/env token
  ergonomics until a hosted browser surface exists.

## Problem
Without a formal contract, apps can blur long-lived Gateway user tokens with
browser sessions, duplicate token handling, store bearer tokens in browser
storage, or implement inconsistent logout/revocation semantics. Admin UI work
would then normalize brittle auth behavior.

## What we want to do
Define and implement a hosted browser-session contract for Gateway-connected
apps. Apps should exchange a Gateway user token for an app/browser session and
then proxy Gateway requests with server-side session credentials. Browser code
must not retain the bearer token after connection.

## Requirements
- Browser apps never store Gateway bearer tokens in `localStorage`,
  `sessionStorage`, IndexedDB, or readable cookies in hosted mode.
- Session cookies are `HttpOnly`, `Secure` when served over HTTPS, use an
  explicit `SameSite` posture, and have deliberate domain/path scoping.
- Mutating routes have a CSRF posture appropriate to the deployment mode.
- Sessions have expiry, logout, and server-side revocation behavior.
- A rotated or disabled Gateway user token invalidates future session creation;
  policy defines whether existing sessions are revoked immediately.
- Error and discovery responses distinguish unauthenticated, expired,
  revoked, and forbidden states without leaking hidden resources.
- Local/offline app modes may keep their existing development ergonomics, but
  hosted mode must use this contract.

## Scope
- Gateway-connected browser session contract.
- Shared app expectations for Flow, Code Web, Observer, Gateway Console, and
  future browser apps.
- Tests for cookie flags, logout, revocation, and token-storage audit.

## Non-goals
- Do not replace Gateway user tokens as the principal credential.
- Do not force terminal/local-only apps to use browser cookies.
- Do not implement a full external IdP/OIDC flow in this item.

## Dependencies and related tasks
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0145_gateway_admin_console_bootstrap.md`
- `../../completed/0149_cross_app_gateway_auth_defaults_convergence.md`
- `docs/backlog/completed/0141_flow_browser_session_gateway_auth.md`

## Expected outcomes
- Hosted browser apps share one clear session/security model.
- Admin console work does not rely on raw bearer-token storage in the browser.
- Cross-app convergence has a concrete auth contract to implement against.

## Validation
- Browser tests prove Gateway bearer tokens are not present in web storage.
- Cookie flag tests cover hosted and local-dev variants.
- Logout and revocation tests prevent continued Gateway proxying.
- CSRF tests cover mutating routes exposed through app sessions.
- Origin tests cover same-origin/localhost and explicitly allowlisted
  cross-origin hosted apps while rejecting untrusted origins.

## Recent validation
- `npm test -- --run src/lib/storage.test.ts` in `abstractcode/web` -> 1 passed.
- `npm test -- --run src/ui/auth_storage.test.ts` in `abstractobserver` -> 1 passed.
- Stub-Gateway hosted-session proxy smoke tests for AbstractCode Web,
  AbstractObserver, and AbstractFlow static server -> passed.
- `npm run build` in `abstractcode/web`, `abstractobserver`, and
  `abstractflow/web/frontend` -> passed.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_security_middleware_unit.py abstractflow/tests/test_gateway_connection_config.py abstractflow/tests/test_web_gateway_proxy_auth.py` -> 44 passed.
- `npm run build` in `abstractflow/web/frontend` -> TypeScript and Vite production build passed.
- `python -m pytest abstractgateway/tests/test_gateway_principal_auth.py abstractgateway/tests/test_gateway_principal_isolation_matrix.py abstractgateway/tests/test_capabilities_endpoint_contract.py abstractgateway/tests/test_abstractflow_editor_gateway_contract.py -q` -> 26 passed.
- `python -m py_compile abstractgateway/src/abstractgateway/routes/gateway.py abstractgateway/src/abstractgateway/security/sessions.py abstractgateway/src/abstractgateway/security/gateway_security.py` -> passed.

## Progress checklist
- [x] Define session issuance and cookie semantics for Gateway and Flow.
- [x] Define CSRF and logout/revocation behavior for Gateway and Flow.
- [x] Add shared hosted-mode detection expectations.
- [x] Add Gateway/Flow tests and app migration guidance.
- [x] Migrate Code Web and Observer from raw browser bearer-token storage.
- [x] Add full cookie/origin/session matrix tests across HTTP, HTTPS,
  same-origin, allowlisted cross-origin, untrusted cross-origin, expiry, logout,
  and token-rotation revocation.

## Guidance for the implementing agent
Keep user tokens and browser sessions separate. A token authenticates a
principal to Gateway; a browser session lets a specific app/browser continue
acting for that principal under tighter cookie, expiry, and revocation rules.

--- docs/backlog/completed/0154_multi_user_security_release_blockers.md ---
# Planned: Multi-user security release blockers

## Metadata
- Created: 2026-05-30
- Status: Completed
- Completed: 2026-05-30

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033
- ADR impact: None. This item enforces the current Gateway control-plane and browser-session decisions.

## Context
The multi-user Gateway work introduced user-authenticated browser sessions,
per-principal runtime routing, and hosted app proxy sessions. A review found
three release-blocking gaps: retained runtime data could be reassigned after
user deletion, Code Web and Observer allowed browser-supplied Gateway URL
changes on hosted hosts, and the published Gateway/Flow launcher did not
bootstrap Gateway users for browser login.

## Current code reality
- `abstractgateway/src/abstractgateway/users.py` rejects duplicate runtime ids
  among live users but, before this item, user deletion removed the only
  assignment record while retaining runtime data on disk.
- `abstractflow` rejects browser Gateway URL changes on non-local hosts unless
  explicitly enabled, but `abstractcode/web/bin/cli.js` and
  `abstractobserver/bin/cli.js` did not have the same guard.
- `scripts/gateway-flow-local.sh` enables Gateway user auth, prepares the
  default `admin` user, and prints Flow login credentials. `scripts/gateway-flow.sh`
  still used only the legacy Gateway token and did not create a browser-login user.

## Problem
These gaps can break isolation, allow hosted app proxy misuse, or make the
published startup path unusable for the new browser-session auth model.

## What we want to do
Close the release blockers with targeted changes that preserve the current
architecture: Gateway owns users/runtime assignment, hosted apps proxy through
browser sessions, and scripts print only the user credentials needed by Flow.

## Why
Multi-user Gateway support must fail closed before release. A user or admin
should not accidentally route one person's retained runtime data to another
principal, and hosted apps must not become arbitrary browser-directed proxies.

## Requirements
- Deleting a Gateway user reserves that user's runtime id while runtime data is
  retained, preventing assignment to a different principal in the same tenant.
- Flow, Code Web, and Observer share the same hosted/non-local browser Gateway
  URL mutation rule.
- Published-package `gateway-flow.sh` enables user auth, prepares an `admin`
  user by default, caches the generated user token locally, and prints Gateway
  URL/user/token for Flow sign-in.
- `.DS_Store` files are ignored and must not remain tracked.

## Suggested implementation
- Add runtime reservation/tombstone records to the Gateway user registry.
- Add Code Web and Observer URL guards matching Flow and cover them with
  hosted-server tests.
- Mirror the local launcher's user-bootstrap behavior in the published script.
- Remove tracked `.DS_Store` files and keep ignore files aligned.

## Scope
- AbstractGateway user registry and console copy.
- AbstractCode Web and AbstractObserver packaged Node servers plus tests.
- Root startup scripts and docs.
- Ignore hygiene for `.DS_Store`.

## Non-goals
- Do not add a purge, restore, or runtime-transfer UI in this item.
- Do not extract a shared hosted proxy helper unless implementation pressure is
  proven by tests or another drift incident.
- Do not change Core or Runtime behavior.

## Dependencies and related tasks
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0153_gateway_browser_session_security_contract.md`
- `../../completed/0149_cross_app_gateway_auth_defaults_convergence.md`

## Expected outcomes
- A deleted user's retained runtime cannot be assigned to another user.
- Hosted Code/Observer reject remote-host Gateway URL changes just like Flow.
- `./scripts/gateway-flow.sh` produces usable `admin` browser-login credentials.
- Release hygiene no longer includes tracked `.DS_Store` files.

## Validation
- Gateway user-registry tests cover delete-plus-cross-user-runtime-reuse.
- Code/Observer hosted server tests cover remote-host URL mutation rejection.
- `bash -n scripts/gateway-flow.sh scripts/gateway-flow-local.sh`.
- Targeted Gateway, Flow, Code, and Observer test suites pass.

## Progress checklist
- [x] Add Gateway runtime reservations.
- [x] Add Code Web and Observer hosted URL guards.
- [x] Align published launcher user bootstrap.
- [x] Clean `.DS_Store` tracking/ignore state.
- [x] Update docs and completion report.

## Guidance for the implementing agent
Keep the fixes narrow. The security model belongs in Gateway and in hosted app
proxy boundaries; do not move user/routing ownership into Flow, Code, Observer,
Core, or Runtime.

## Architecture decision summary

Decision question: how should the release blockers be closed without blurring
Gateway/app responsibilities?

Alternatives considered:
- Disable instead of delete users. This would preserve runtime ownership, but
  would change the user-management API and make the console's delete action
  misleading.
- Add retained-runtime reservations on delete. This preserves existing delete
  UX while preventing cross-principal runtime reassignment.
- Add a full purge/transfer workflow now. This would be most explicit, but it
  adds admin UX and irreversible-data semantics beyond the release blocker.

Chosen design: delete removes the user credential and creates a retained-runtime
reservation. A different same-tenant principal cannot reuse the runtime id while
data is retained. Recreating the same logical principal may reclaim its own
reservation. Explicit purge/transfer remains a future admin workflow, not a
silent side effect.

For hosted app proxy duplication, the chosen near-term design is conformance
tests plus matching URL guards in Code Web and Observer. A shared helper is
proposed in `0155`, but not extracted in this item because the immediate
security risk is closed by tests and the package boundary is not yet proven.

## Completion report

Date: 2026-05-30

Summary:
- Added `runtime_reservations` to the Gateway user registry. Deleting a user now
  reserves the retained runtime id for that principal and blocks assigning it
  to another user in the same tenant.
- Updated Gateway Console delete copy so admins see that runtime data is
  retained and the runtime id remains reserved.
- Added hosted non-local Gateway URL guards to AbstractCode Web and
  AbstractObserver packaged Node servers, matching Flow's behavior.
- Tightened Flow/Code/Observer host checks so forwarded host headers are used
  only when explicit trust-proxy env vars are set.
- Added Code/Observer hosted-server tests proving remote-host browser Gateway
  URL changes are rejected, including forged `X-Forwarded-Host` loopback
  headers.
- Updated `scripts/gateway-flow.sh` to enable Gateway user auth, prepare the
  default `admin` browser user, cache the generated user token, and print the
  Gateway URL/user/token for Flow sign-in.
- Removed tracked `.DS_Store` files from AbstractObserver and added the missing
  ignore rule.
- Updated user-facing docs, backlog, and LLM context files.

Files or symbols touched:
- `abstractgateway/src/abstractgateway/users.py`
- `abstractgateway/src/abstractgateway/console.py`
- `abstractgateway/tests/test_gateway_principal_auth.py`
- `abstractcode/web/bin/cli.js`
- `abstractcode/web/src/lib/hosted_gateway_url_guard.test.ts`
- `abstractobserver/bin/cli.js`
- `abstractobserver/src/ui/hosted_gateway_url_guard.test.ts`
- `abstractobserver/.gitignore`
- `abstractflow/web/backend/services/gateway_connection.py`
- `abstractflow/web/backend/routes/connection.py`
- `abstractflow/web/frontend/bin/cli.js`
- `abstractflow/web/frontend/vite.config.ts`
- `abstractflow/tests/test_gateway_connection_config.py`
- `scripts/gateway-flow.sh`
- Root, Code, Observer, and Gateway docs/LLM context files.

Validation:
- `python -m pytest tests/test_gateway_principal_auth.py tests/test_gateway_principal_isolation_matrix.py tests/test_gateway_security_middleware_unit.py tests/test_gateway_workflow_catalog_acl.py tests/test_gateway_console.py tests/test_gateway_install_profiles.py tests/test_gateway_embeddings_endpoint.py -q` in `abstractgateway` -> 54 passed.
- `python -m pytest tests/test_gateway_connection_config.py tests/test_web_gateway_proxy_auth.py -q` in `abstractflow` -> 21 passed, 2 FastAPI deprecation warnings.
- `node --check bin/cli.js && npm test -- --run src/lib/storage.test.ts src/lib/hosted_gateway_url_guard.test.ts` in `abstractcode/web` -> 2 passed.
- `node --check bin/cli.js && npm test -- --run src/ui/auth_storage.test.ts src/ui/hosted_gateway_url_guard.test.ts` in `abstractobserver` -> 2 passed.
- `node --check web/frontend/bin/cli.js && npm --prefix web/frontend run build` in `abstractflow` -> passed.
- `python -m py_compile web/backend/services/gateway_connection.py web/backend/routes/connection.py` in `abstractflow` -> passed.
- `bash -n scripts/gateway-flow.sh scripts/gateway-flow-local.sh` -> passed.
- Root, Gateway, Flow, Code, and Observer `llms-full` generation -> passed.

Residual risks:
- The explicit retained-runtime purge/transfer workflow was intentionally left
  out of this release-blocker item and is handled by follow-up item `0156`.
- Code Web and Observer still duplicate hosted proxy code. Proposed item `0155`
  records the extraction threshold; current protection is conformance tests.

--- docs/backlog/completed/0156_retained_runtime_admin_lifecycle.md ---
# Completed: Retained runtime admin lifecycle

## Metadata
- Created: 2026-05-30
- Status: Completed
- Completed: 2026-05-30

## ADR status
- Governing ADRs: None
- ADR impact: None

## Context
Gateway user deletion now removes account/token access while retaining the
runtime data directory and reserving the runtime id for the deleted principal.
That prevents accidental cross-user data exposure, but it leaves admins without
an explicit way to intentionally purge retained runtime data or transfer it to
another user.

## Current code reality
- `abstractgateway/src/abstractgateway/users.py` stores live users and
  `runtime_reservations` in the Gateway user registry.
- `GatewayUserRegistry.create_user()` and `update_user()` reject reuse of a
  retained runtime reservation by another principal.
- `GatewayUserRegistry.delete_user()` creates a retained-runtime reservation.
- `abstractgateway/src/abstractgateway/routes/gateway.py` exposes admin user
  CRUD, but no retained-runtime lifecycle routes.
- `abstractgateway/src/abstractgateway/console.py` tells admins that runtime
  data is retained, but has no reservation table, transfer action, or purge
  action.

## Problem
The retained-runtime safety guard is secure but operationally incomplete.
Admins can see that deletion retained data only through the delete confirmation
copy and registry file internals. They cannot intentionally purge stale data or
transfer retained data to a new owner through supported Gateway APIs.

## What we want to do
Add explicit admin-only lifecycle operations for retained runtime reservations:
list, transfer, and purge. Transfer must be intentional and auditable through
the registry. Purge must remove retained runtime files before releasing the
runtime id for reuse.

## Why
This keeps the secure default while giving admins a deliberate recovery path for
real account lifecycle events: employee departure, account rename, mistaken
delete, or data-retention cleanup.

## Requirements
- Admins can list retained runtime reservations.
- Non-admin users cannot list, purge, or transfer retained runtimes.
- Transfer assigns a retained runtime to an existing same-tenant user and
  reserves that user's previous runtime id.
- Purge requires an exact runtime-id confirmation and deletes the retained
  runtime directory before releasing the reservation.
- Runtime file deletion must stay inside the Gateway per-user runtime root.
- The Gateway Console exposes transfer and purge actions with confirmations.
- Tests prove cross-user reuse remains blocked until explicit purge or transfer.

## Suggested implementation
- Extend `GatewayUserRegistry` with reservation listing, lookup, release, and
  transfer helpers.
- Add admin routes under `/api/gateway/admin/runtime-reservations`.
- Add a Gateway service-cache invalidation helper for affected runtime ids.
- Add a console section for retained runtime reservations.
- Add focused Gateway tests around RBAC, transfer, purge, and data deletion.

## Scope
- AbstractGateway registry, admin API, console, tests, and docs.
- Root/Gateway docs and AI-readable docs updates.

## Non-goals
- No runtime explorer UI.
- No partial artifact-level purge.
- No automatic data migration between different runtime layouts.
- No cross-tenant transfer.

## Dependencies and related tasks
- `0145_gateway_admin_console_bootstrap.md`
- `0146_gateway_rbac_scope_policy_matrix.md`
- `0154_multi_user_security_release_blockers.md`

## Expected outcomes
- Deleted users still protect retained data by default.
- Admins have an explicit, confirmed purge path.
- Admins have an explicit, confirmed transfer path.
- Tests and docs describe the lifecycle clearly.

## Validation
- `python -m pytest tests/test_gateway_principal_auth.py -q`
- `python -m pytest tests/test_gateway_console.py -q`
- `python -m py_compile src/abstractgateway/users.py src/abstractgateway/routes/gateway.py src/abstractgateway/service.py src/abstractgateway/console.py`

## Progress checklist
- [x] Add registry lifecycle helpers.
- [x] Add admin routes and service-cache invalidation.
- [x] Add Gateway Console retained-runtime UI.
- [x] Add tests for RBAC, transfer, purge, and reuse.
- [x] Update docs and backlog completion report.

## Guidance for the implementing agent
Preserve the conservative default. A retained runtime id must never become
reusable just because the account row disappeared; reuse must follow an
explicit purge or transfer operation.

## Completion report

Date: 2026-05-30

Summary:
- Added retained-runtime lifecycle helpers to the Gateway user registry.
- Added admin-only list/transfer/purge routes under
  `/api/gateway/admin/runtime-reservations`.
- Added service-cache invalidation for affected runtime ids after transfer or
  purge.
- Added a `purging` reservation state so concurrent transfer attempts cannot
  claim a retained runtime between purge validation and file deletion.
- Added a Gateway Console retained-runtime table with transfer and purge actions
  behind confirmation modals.
- Added tests proving non-admin denial, purge-before-reuse, transfer to an
  existing same-tenant user, previous-runtime reservation, and continued
  cross-user reuse blocking.

Files or symbols touched:
- `abstractgateway/src/abstractgateway/users.py`
- `abstractgateway/src/abstractgateway/routes/gateway.py`
- `abstractgateway/src/abstractgateway/service.py`
- `abstractgateway/src/abstractgateway/console.py`
- `abstractgateway/tests/test_gateway_principal_auth.py`
- `abstractgateway/tests/test_gateway_console.py`
- `abstractgateway/docs/security.md`
- `abstractgateway/docs/configuration.md`
- `abstractgateway/README.md`
- `abstractgateway/llms.txt`
- `docs/guide/gateway-security.md`
- `docs/configuration.md`
- `docs/api.md`
- `llms.txt`

Validation:
- `python -m pytest tests/test_gateway_principal_auth.py tests/test_gateway_console.py -q`
  in `abstractgateway` -> 18 passed.
- `python -m pytest tests/test_gateway_principal_isolation_matrix.py tests/test_gateway_security_middleware_unit.py tests/test_gateway_workflow_catalog_acl.py -q`
  in `abstractgateway` -> 26 passed.
- `python -m py_compile src/abstractgateway/users.py src/abstractgateway/routes/gateway.py src/abstractgateway/service.py src/abstractgateway/console.py`
  in `abstractgateway` -> passed.

Review notes:
- Code quality: purge atomically marks reservations as `purging` before file
  deletion, keeps deletion scoped under
  `<ABSTRACTGATEWAY_DATA_DIR>/users/<tenant>/<runtime>`, and leaves the
  reservation in place if file deletion fails.
- Architecture: Gateway remains the owner of user/runtime assignment and
  retained-runtime lifecycle. Runtime internals are not asked to understand
  Gateway user ownership.
- Naive user: the console now shows retained runtimes directly instead of
  making admins infer them from failed user creation.
- Expert user: the API exposes explicit lifecycle routes and returns data-path
  diagnostics for admin inspection.
- Operations: transfer does not copy data; it changes routing ownership. Purge
  deletes the retained runtime root and then releases the reservation.

Residual risks:
- There is still no rich runtime explorer or artifact-level delete/export for
  retained runtime data. That remains in the proposed runtime explorer track.
- Transfer is same-tenant and existing-user only by design. Account rename flows
  that need create-and-transfer can create the target first, then transfer.

--- docs/backlog/completed/0157_gateway_provider_endpoint_profiles.md ---
# Completed: Gateway provider endpoint profiles

## Metadata
- Created: 2026-05-31
- Status: Completed
- Completed: 2026-05-31

## ADR status
- Governing ADRs: ADR-0033, ADR-0035
- ADR impact: May revise existing ADR after the wider provider-secret vault and workflow export/import rules settle.

## Context
Gateway Console could edit capability defaults for the current principal:
route, provider, model, and optional base URL. That was not enough to configure
an OpenAI-compatible endpoint with the API key needed by hosted, multi-user
Gateway deployments. Users also needed more than one endpoint; defaults and
custom endpoints are separate concerns.

## Problem
Users need to configure OpenAI-compatible and other custom remote endpoints once
in Gateway, then select and reuse them from Flow nodes without hardcoding raw
secrets in workflow JSON, browser storage, run ledgers, or exported bundles.

## Implemented design
Gateway now owns provider endpoint profiles:

- `id`: stable local identifier.
- `display_name`: user-facing label.
- `description`: operator/user explanation of what the endpoint is for.
- `provider_family`: canonical provider implementation such as
  `openai-compatible`, `openai`, `openrouter`, or `anthropic`.
- `base_url`: optional endpoint URL; blank means provider default.
- `api_key`: stored server-side and returned only as non-secret status and
  fingerprint.
- `scope`: `user` or `gateway`; gateway scope requires admin.
- `capabilities`: text, embeddings, image, video, voice, music, or other route
  families.
- `allowed_models`: optional static allowlist; otherwise Gateway asks the
  underlying discovery facade.

Enabled profiles surface through provider discovery as virtual providers such
as `endpoint:office-vllm`. Runtime resolves that virtual id through a
host-provided resolver into the real provider family, base URL, and API key
only for the transient provider call.

## Scope
- AbstractGateway profile store, config API, discovery integration, console UI,
  bundle-host resolver, tests, and docs.
- AbstractRuntime generic optional resolver hook and local multi-client support
  for per-call provider construction with profile base URL/key.

## Non-goals
- No browser-stored provider keys.
- No raw key in workflow JSON, exported bundles, discovery responses, or Runtime
  observability.
- No new provider class per endpoint alias.
- No full workflow export/import endpoint-requirement mapper yet.
- No encrypted-at-rest vault yet; the initial local profile JSON is permissioned
  with `0600`, and the broader vault/audit policy remains under `0147`.

## Completion report

Date: 2026-05-31

Summary:
- Added `ProviderEndpointProfileStore` under AbstractGateway with public
  non-secret profile views and private runtime resolution.
- Added `/api/gateway/config/provider-endpoint-profiles` CRUD routes.
- Added `/api/gateway/config/provider-endpoint-profiles/discover-models` so the
  console can preview models from a draft or saved endpoint profile without
  exposing the raw key.
- Added profile-backed provider discovery and model discovery. Profiles with
  an allowlist return that model list directly; other profiles discover through
  the configured provider family, base URL, and profile key.
- Added Gateway Console controls for profile id, name, description, provider
  family, scope, base URL, API key, capabilities, and a discovered model picker
  where selected models become the optional allowlist.
- Added virtual provider labels to console provider selectors so profiles are
  selectable like normal providers while preserving the `endpoint:*` id.
- Added Runtime LLM-call profile resolution, provider/base URL/key injection,
  and redaction from persisted observability traces.
- Added local `MultiLocalAbstractCoreLLMClient` support for per-call provider
  construction from profile `base_url` and `api_key`.
- Added bundle-host resolver wiring so Gateway-hosted runs can resolve virtual
  providers without Runtime importing Gateway.

Validation:
- `python -m pytest abstractgateway/tests/test_gateway_provider_endpoint_profiles.py abstractgateway/tests/test_gateway_discovery_endpoints.py abstractgateway/tests/test_gateway_console.py abstractruntime/tests/test_provider_endpoint_profile_resolution.py -q` -> 15 passed.
- `python -m compileall -q abstractgateway/src/abstractgateway abstractruntime/src/abstractruntime` -> passed.

Review notes:
- Code quality: raw keys are write-only through API/UI responses and redacted in
  Runtime observability. Scope changes upsert before deleting the old scoped row
  to avoid losing a profile on validation failure.
- Architecture: Gateway owns endpoint profiles and credentials; Runtime exposes
  only a generic optional resolver hook and does not import Gateway.
- Naive user: Gateway Console presents the endpoint as a named reusable object
  with description, a discover-models action, and a visible virtual provider id
  to copy/select.
- Expert user: profiles support static model allowlists, dynamic discovery,
  provider-family routing, gateway/user scope, and direct use in capability
  defaults or Flow node provider pins.
- Operations: initial storage is local JSON under the relevant Gateway data
  plane with `0600` permissions. A stronger vault/encryption/audit layer remains
  a follow-up under `0147`.

Residual risks:
- Workflow export/import still needs a portable endpoint requirement model so a
  shared workflow can ask the importing user to map or create an endpoint
  profile without exporting secrets.
- Profile resolution is implemented for text provider/model discovery and
  Runtime `LLM_CALL`/Agent execution, including output-selector calls that flow
  through that effect. Direct Gateway embedding/media catalog routes can adopt
  the same profile projection when those UI paths need virtual endpoint
  selection outside `LLM_CALL`.
- Gateway-scoped profile policy is currently admin-only create/update/delete and
  inherited discovery/use. Finer tenant ACLs can be added when endpoint sharing
  policy becomes stricter.
- Secrets are permissioned local JSON, not encrypted at rest. That is acceptable
  for the initial Gateway-local control-plane path but should not be treated as
  the final hosted vault design.

--- docs/backlog/proposed/gateway-control-plane/README.md ---
# Gateway control plane proposals

## Status
Proposed.

## Purpose
These proposals preserve package-boundary options that are plausible but not
yet implementation commitments. The planned Gateway control-plane track should
prove the API and UX needs first.

## Items
- `0151_runtime_explorer_contract.md`: define whether runtime browsing becomes
  Gateway Console tabs, Observer pages, or a future `abstractexplorer`.
- `0152_abstractmanager_package_extraction.md`: decide whether the Gateway
  admin/config UI should later become a separate `abstractmanager` package.
- `0155_hosted_proxy_shared_helper_extraction.md`: decide when repeated hosted
  browser-session proxy logic in Node apps should become a shared helper rather
  than package-local code plus conformance tests.

## Reading order
Read the planned track first:
`../../planned/gateway-control-plane/README.md`.

## Non-goals
These proposals do not authorize new packages yet. They record names and
boundaries to revisit after Gateway Console v0, RBAC hardening, and config APIs
land.

--- docs/backlog/proposed/gateway-control-plane/0151_runtime_explorer_contract.md ---
# Proposed: Runtime Explorer contract

## Metadata
- Created: 2026-05-30
- Status: Proposed
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021
- ADR impact: May revise existing ADR

## Context
Users need to understand their runtime: runs, ledgers, artifacts, memories,
workflows, workspaces, quotas, storage, and recent activity. Gateway can expose
the data, Observer already visualizes runs, and a future `abstractexplorer`
could become a dedicated runtime browser.

## Current code reality
- Gateway has many endpoints for runs, artifacts, workflows, prompt cache,
  workspaces, schedules, and maintenance.
- Observer already handles run/ledger observability and some broad operational
  surfaces.
- Gateway Console v0 is planned for account/admin/runtime summary, not deep
  runtime exploration.
- Hosted user auth now routes normal users to per-principal runtime data
  planes; any explorer contract must derive the browsed owner from the current
  principal unless an admin-only audited route explicitly selects another user.

## Problem or opportunity
Runtime state is opaque. Users want a file-system-like way to list, search,
inspect, export, delete, and understand their own runtime data. It is unclear
whether that belongs in Gateway Console, Observer, or a new app.

## Proposed direction
Define an API-first Runtime Explorer contract before creating a package. The
contract should cover list/search/detail/export/delete for current user's runs,
artifacts, memory, workflows, sessions, workspace files, prompt-cache metadata,
and storage usage. Keep admin cross-user exploration behind explicit RBAC.
Before promotion, classify data by sensitivity: prompts, tool parameters,
artifacts, memory, logs, PII, secrets, deleted data, retention state, and export
redaction needs.

Start with a read-only normalized resource envelope:
`type`, `id`, `scope`, `owner`, `sensitivity`, `created_at`, `updated_at`,
`summary`, `metadata`, `links`, and permission-aware `actions`. Keep
`browse/search/detail` separate from `export/delete`; export and deletion need
separate RBAC, audit logging, retention semantics, and confirmation UX.

The runtime should feel queryable like an operating/file system, but that does
not mean it should expose raw files first. The first API should expose typed
runtime resources (runs, artifacts, memories, workflows, sessions, prompt-cache
entries, workspace files, and storage summaries) with cursor pagination,
date/type filters, and redacted previews.

## Why it might matter
If runtime exploration becomes a large UX, `abstractexplorer` is a clean name
and boundary. If it stays small, it can remain Gateway Console tabs or Observer
pages.

## Promotion criteria
- Gateway Console v0 and Observer both need overlapping runtime browsing.
- Users need cross-cutting runtime search beyond run observability.
- RBAC policy matrix can safely expose explorer routes.
- Data classification, pagination, quota, export redaction, delete/retention,
  and audit requirements are written down.

## Validation ideas
- Alice/Bob cannot explore each other's runtime data.
- User can search own artifacts/runs/memory by metadata.
- Admin cross-user views require admin role and audit logging.
- Non-admin explorer requests cannot pass `owner_id`, `all_owners`, or arbitrary
  runtime paths to escape their principal-derived runtime.
- Export/delete actions require explicit action-level authorization and produce
  audit events.

## Non-goals
- This proposal does not authorize a new package yet.
- Do not build broad runtime exploration before route-family RBAC exists.
- Do not implement delete/export as ordinary browsing actions; treat them as
  high-risk operations with explicit RBAC, audit, and retention semantics.
- Do not turn the initial Gateway Console into a deep explorer before the API
  contract and sensitivity labels exist. It can link to Explorer/Observer once
  the boundary is stable.

## Guidance for future agents
Reserve `abstractexplorer` as a plausible future package name, but start with
contracts and narrow Gateway/Observer integrations.

## Review synthesis - 2026-05-30

Three independent review perspectives converged on the same boundary:

- Product/UX perspective: build Runtime Explorer as a read-only Observer page
  first. A user should be able to inspect their own runs, artifacts,
  session-level memory, workflow references, and storage summaries without
  learning raw Gateway routes. Keep destructive operations and admin
  cross-user views out of v0.
- Security/control-plane perspective: Gateway should own the explorer API
  contract, RBAC, redaction, sensitivity labels, links, and permission-aware
  actions. Normal user routes must derive owner from the authenticated
  principal; do not accept `tenant_id`, `runtime_id`, `owner_id`, raw workspace
  paths, or `all_owners` as ordinary user selectors.
- Architecture perspective: do not create `abstractexplorer` yet. Gateway
  already owns the data access and Observer already owns observability UX. A
  separate package becomes justified only if cross-resource search, saved
  views, export/retention tooling, and runtime "file system" navigation grow
  beyond Observer's natural scope.

If this proposal is promoted, narrow the first planned item to
`runtime_explorer_read_only_v1`: a Gateway envelope contract plus an
Observer-hosted page. The first envelope should cover `run`, `artifact`,
`memory`, `workflow`, and `defaults` resources with bounded previews,
provenance links, sensitivity labels, and action availability. Defer raw
workspace browsing, prompt-cache internals, delete/export, and admin cross-user
runtime browsing until separate RBAC, audit, redaction, and retention semantics
are written.

--- docs/backlog/proposed/gateway-control-plane/0152_abstractmanager_package_extraction.md ---
# Proposed: AbstractManager package extraction

## Metadata
- Created: 2026-05-30
- Status: Proposed
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0021, ADR-0033, ADR-0035
- ADR impact: May revise existing ADR

## Context
Gateway needs an admin/account/config UX. The first version should likely be
Gateway-served to keep first-run setup simple. If the UI grows into a rich
control-plane product, a separate package such as `abstractmanager` may become
cleaner.

## Current code reality
- Gateway owns identity, routing, user CRUD, and control-plane APIs.
- Core owns config/default schema and persistence.
- Flow, Code, Observer, and Assistant are task-specific apps.
- There is no Manager package.

## Problem or opportunity
A built-in Gateway Console can become too large if it tries to own users,
secrets, defaults, workflows, runtime browsing, audit, setup, and operations.
A separate Manager package could improve frontend code quality and release
boundaries, but creating it too early increases package sprawl.

## Proposed direction
Start with Gateway Console v0 inside Gateway. Reassess extraction after admin
console, config/defaults, and workflow ACL pages are real. If extracted,
`abstractmanager` should be a Gateway-hosted or Gateway-connected control-plane
app, not a second authority.
Gateway Console v0 should still be built behind a clean frontend boundary:
typed Gateway API client, no direct Core calls, no app-local auth assumptions,
and asset/package layout that can be extracted later without rewriting
authorization.

## Why it might matter
This keeps initial setup simple while preserving a path to a cleaner product
boundary if the admin/config UX grows.

## Promotion criteria
- Gateway Console frontend becomes too large for Gateway package maintenance.
- Multiple Gateway deployments need the same rich admin UI.
- AbstractUIC components and release flow make a package split cheaper than
  embedding assets in Gateway.
- Console v0, per-principal config/defaults, workflow ACLs, and the
  responsibility split have shipped or been accepted.
- Extraction does not make first-run setup harder.

## Validation ideas
- Compare bundle size, release overhead, install profile complexity, and user
  setup friction before extraction.
- Confirm Manager never bypasses Gateway authorization.

## Non-goals
- Do not create `abstractmanager` before Gateway Console v0 proves the need.
- Do not let Manager own secrets/config independently of Gateway/Core.
- Do not extract merely because the name is attractive; extract only when
  maintenance, reuse, or release pressure proves the package boundary.

## Guidance for future agents
Treat `abstractmanager` as a package-boundary option, not a feature requirement.
The authority remains Gateway plus Core config APIs either way.

--- docs/backlog/proposed/gateway-control-plane/0155_hosted_proxy_shared_helper_extraction.md ---
# Proposed: Hosted proxy shared helper extraction

## Metadata
- Created: 2026-05-30
- Status: Proposed
- Completed: N/A

## ADR status
- Governing ADRs: ADR-0018, ADR-0033
- ADR impact: None unless promoted to a package-boundary change.

## Context
Flow, Code Web, and Observer all implement hosted Gateway browser-session
proxying. Code Web and Observer currently duplicate similar Node server logic
for app cookies, Gateway session exchange, CSRF forwarding, logout, and Gateway
URL selection. A review found real drift: Flow blocked remote-host browser
Gateway URL changes while Code Web and Observer did not.

## Current code reality
- Flow's Python backend and static/Vite server implementations already reject
  browser Gateway URL changes from non-local hosts unless explicitly enabled.
- Code Web and Observer now have matching guards and focused tests, but their
  Node server implementations remain package-local.
- No shared JavaScript package currently owns hosted Gateway proxy semantics.

## Problem or opportunity
Duplicated hosted proxy logic can drift again as app behavior evolves. A shared
helper could reduce security drift, but extracting too early may create a
cross-package abstraction that fits only today's two Node servers and not Flow's
Python host or future apps.

## Alternatives
- Keep package-local code and require conformance tests in every hosted browser
  app. This is small and reversible, but duplicated code remains.
- Extract a tiny shared Node helper for Code Web and Observer only. This reduces
  drift for the duplicated Node servers, but adds a new dependency boundary and
  does not help Flow's Python host.
- Define a language-neutral conformance suite first, then extract helpers only
  when at least two apps need identical behavior beyond tests. This has slower
  reuse but better evidence for the abstraction.

## Recommendation
Use conformance tests immediately and defer helper extraction. Promote this
proposal if another hosted app is added or Code/Observer drift again despite
tests. At that point, extract the smallest shared Node helper that owns only
cookie/session/proxy policy, not app UI or provider/default UX.

## Promotion criteria
- Two or more Node hosted apps need the same code changes at the same time.
- A conformance test catches repeated drift that would be easier to prevent by
  centralizing the helper.
- The helper can stay independent of app layout, routing, and feature flags.

## Non-goals
- Do not force Flow's Python backend into a JavaScript helper.
- Do not create a shared UI component for login/defaults from this proposal.
- Do not move Gateway authorization decisions out of Gateway.

## Validation if promoted
- Shared helper unit tests for cookie flags, URL guards, session exchange,
  logout, CSRF injection, and header stripping.
- App-level tests proving Code Web and Observer still expose the expected API
  shape after adopting the helper.

--- docs/backlog/planned/074_agent_skills_integration.md ---
# 074 — Agent Skills (`SKILL.md`) Integration

**Status**: Planned  
**Date**: 2026-02-21  
**Priority**: Medium–High (interoperability + distribution)  
**Components**: abstractagent, abstractruntime, abstractgateway, docs

## Summary

Add first-class support for the **Agent Skills** ecosystem format (a folder with a required `SKILL.md`) so
AbstractFramework can import/share procedural “skill packs” across hosts and gateway-first deployments.

Key design: **flows run; skills are activated/loaded**. Skill scripts (when enabled) execute only via explicit tools
with approvals and evidence capture.

## Reason

- Skills are an emerging interoperability layer across agent ecosystems (Claude Code/API and third-party packs).
- AbstractFramework already has the right execution substrate (durable runs, tool boundaries, replay-first ledger).
- Skills complement (do not replace) `.flow` bundles: skills are lightweight procedure packs; flows are durable programs.

## Scope

### In scope

- Skill discovery (metadata-only), progressive disclosure, and activation.
- Durable/observable activation:
  - activation and resource reads produce ledger records
  - large skill bodies/resources stored as artifacts (keep run state JSON-safe)
- Optional enforcement of skill `allowed-tools` as a restriction (intersection with run tool allowlists).
- Optional gateway skills registry (list/fetch/install/deprecate) parallel to `.flow` bundle distribution.

### Out of scope (v0)

- “Claude Code extensions” (slash commands, hooks, subagent forks) unless they map cleanly to runtime primitives.
- Provider-specific “container skills” support unless explicitly configured (keep `abstractcore` lean).
- Implicit script execution. Skill scripts only run as explicit tools.

## Proposed interaction model

1) **Run-attached skills (primary)**: hosts attach available-skill metadata to a run; users activate skills explicitly.
2) **Bundle-declared dependencies (secondary)**: `.flow` bundles may declare `skills.required` / `skills.defaults` via
   `manifest.metadata` without changing the bundle format.
3) **Bundle-embedded skills (optional later)**: embed skills under bundle `assets/*` for hermetic distribution.

## Dependencies / decisions

- Skill identity/version semantics:
  - spec-level identity is the skill `name` (leaf directory name; constrained format)
  - additional namespacing (publisher/source) is optional but may be needed to avoid collisions across multiple roots/registries
  - version can live in `metadata` (spec) and/or be derived from content hash (host policy)
- Default search paths (user + project) and precedence rules.
- Runtime data model for active skills (likely under `_runtime` namespace).
- Security policy for `allowed-tools` and for script execution (approvals + sandboxing).
- `allowed-tools` parsing policy:
  - field is experimental and often uses environment-specific tokens (e.g., Claude Code tool names)
  - enforce only when tokens can be mapped to AbstractFramework tool names; otherwise emit `#FALLBACK` and do not relax tool policy
- Authoring UX for bundle-declared skill dependencies:
  - VisualFlow JSON currently has no `metadata` field, and the gateway publish path auto-generates manifest metadata.
  - If we want `manifest.metadata.skills.*` to be author-editable, we need an authoring surface (CLI metadata args,
    Flow Editor fields, or extend the VisualFlow schema).

## Plan (high level)

1) Add a small shared parser/loader library (recommended: new `abstractskills` package).
2) Add local host UX in AbstractCode/Assistant: discovery + explicit activation.
3) Add runtime-owned activation handler + ledger + artifacts + allowlist intersection.
4) Add gateway skills registry (optional): distribution and thin-client discovery.
5) Add script-to-tool mapping with evidence/approvals (safe-by-default).

## Acceptance criteria

- Metadata discovery does not bloat prompts (caps + progressive disclosure).
- Activation is durable and replayable:
  - skill bodies/resources are artifact-backed when large
  - activation records a content hash (and/or the artifact id) so resumed runs don’t silently pick up modified skill files
- `allowed-tools` restricts execution; out-of-policy calls are denied with actionable `#FALLBACK`.
- No silent fallbacks; truncation is labeled `#TRUNCATION`.

## References

- Proposal guide: `docs/guide/agent-skills.md`
- Detailed phased plan: `docs/backlog/planned/074_agent_skills_integration_plan.md`
- Research notes (spec + ecosystem scan): `docs/skills/`

--- docs/backlog/planned/074_agent_skills_integration_plan.md ---
# Agent Skills integration plan (phased) — AbstractFramework

Supplement to: `docs/backlog/planned/074_agent_skills_integration.md`

## Scope and goal

Integrate the **Agent Skills** (SKILL.md) format into AbstractFramework so that:

- skills are **discoverable** (local + gateway-first),
- skills are **loaded progressively** (metadata first; full content on activation),
- skill usage is **durable + observable** (ledger-recorded, replay-first),
- skill scripts are **safe by default** (explicit approvals, sandboxed execution, no silent fallbacks),
- the integration stays **modular** (does not bloat `abstractcore` or break layering).

This plan focuses on the core packages and contracts:
`abstractcore`, `abstractruntime`, `abstractagent`, `abstractgateway`, plus optional `abstractmemory`/`abstractsemantics`.

## What we learned (clarifications from the spec/ecosystem)

- The Agent Skills spec requires `SKILL.md` with YAML frontmatter including at least `name` + `description`.
- The spec constrains `name` (1–64 chars, lowercase alnum + hyphens) and requires it to match the skill’s directory name.
- The spec also defines optional fields (notably `license`, `compatibility`, `metadata`) and an **experimental** `allowed-tools` field.
- Skills support two primary integration shapes:
  - **Filesystem-based** (local): the agent reads skill folders from disk.
  - **Tool-based** (remote): the agent requests skill content via a tool/API.
- The ecosystem often packages skills as a zipped **`.skill` file** (convention used by Anthropic tooling), even though the base spec is folder-oriented.
- Claude Code adds extra features (slash commands, hooks, subagents) that are useful but **not** required to get value in AbstractFramework.

## Non-negotiable constraints (AbstractFramework architecture)

These come from the implemented contracts in `abstractruntime` + `abstractgateway`:

- **Durable state is JSON-safe** (`RunState.vars`); large content must be artifact-backed.
- **Replay-first**: the ledger is source-of-truth; streaming is an optimization.
- **Tool boundary**: tool schemas may cross boundaries; tool callables do not. Side effects must remain host-executed.
- **No silent fallbacks**: degraded paths must emit actionable `#FALLBACK` warnings; any truncation must be labeled `#TRUNCATION`.

## Skills vs flows (comparison + recommendation)

**Which is “more advanced”?**
- **Flows are more advanced as an execution model** inside AbstractFramework: they are durable, replayable programs (a persisted state machine) with explicit waits, tool boundaries, and ledger visibility.
- **Skills are more advanced as a portability/distribution format** across agent ecosystems: they are a lightweight, tool-agnostic packaging of procedures, prompts, scripts, and references.

**Can every skill be modeled as a flow?**
- **Conceptually: yes.** A skill is “a procedure + resources”; a flow is “a durable procedure.” If the host has the needed tools, a flow can orchestrate the same steps (including loops, approvals, and evidence capture).
- **Practically: the limiting factor is tool availability and environment assumptions**, not the flow model. Many ecosystem skills implicitly assume a specific toolset (Claude container tools, Playwright installed, doc tooling present, etc.). AbstractFramework can model the workflow, but it must also supply or map the required tools.
- **Some skills are not worth turning into flows**: “guidelines/checklists/style” skills are better as *optional prompt modules* that a generic agent flow can load, rather than as their own executable workflows.

### Recommended interaction model (v0)

Treat skills as **data modules** that can be attached to runs and optionally referenced by workflows.
In AbstractFramework terms: **flows run; skills are activated/loaded** (and skill scripts only execute as explicit tools).

1) **Run-attached skills (primary)**
   - A client/host (AbstractCode / AbstractAssistant / thin client via gateway) attaches `available_skills` metadata to the run and activates skills explicitly.
   - The agent workflow remains a normal `abstractcode.agent.v1` flow (or AbstractAgent pattern) that knows how to load/activate skills via a runtime-owned handler.

2) **Bundle-declared skill dependencies (secondary)**
   - A `.flow` bundle may declare skill dependencies in `manifest.metadata` (no format change required).
   - Example shape:
     - `skills.required`: list of `{id, version?}` that must be present
     - `skills.defaults`: list of `{id, version?}` to auto-activate at run start
   - This keeps workflows small and allows organizations to standardize “this workflow expects these skills”.

3) **Bundle-embedded skills (optional; later)**
   - WorkflowBundles already support `assets/*` in the format, but the current packer does not populate `manifest.assets`.
   - If we want hermetic distribution (“workflow + its skills in one file”), we can extend pack/unpack tooling to include `skills/<id>/SKILL.md` and resources as bundle assets, and expose them through the gateway like other bundle bytes.

### Implementation reality check (what fits best with existing code)

AbstractRuntime’s AbstractCore integration already supports **runtime-owned tools** via the `TOOL_CALLS` effect handler
(example: `open_attachment`). This is the best “lowest-friction” way to integrate skills without introducing new effect
types or special-casing flows:

- Add runtime-owned tool specs (no host callable) like:
  - `list_skills()` → returns metadata-only list (progressive disclosure)
  - `open_skill(skill_id, version?, resource_path?)` → returns full `SKILL.md` (and optionally a specific resource),
    snapshotting content into `ArtifactStore` (recording a content hash) and returning artifact refs for replay safety
  - optional `activate_skill(skill_id, ...)` → updates `_runtime.skills.active` and applies `allowed-tools` as a
    restriction (intersection with the run’s allowed tool policy)
- Execute these inside the existing `TOOL_CALLS` handler (same pattern as `open_attachment`), so:
  - activation/read events are ledger-recorded like any other effect
  - runs remain JSON-safe (bodies/resources artifact-backed when large)
  - flows can compose over skills naturally using existing Tool/CallTool nodes (no new VisualFlow node type required)

**Important edge case (passthrough/untrusted tool execution):**
runtime-owned tools cannot be interleaved with delegated tool execution. The existing `open_attachment` logic already
detects delegating executors and falls back to a durable WAIT that the host must resume; the skills tools should follow
the same contract.

## Proposed component map (where code should live)

### A) New small library: `abstractskills` (recommended)

Create a tiny, dependency-light package (like `abstractsemantics`) to avoid sprinkling parsers across clients:

- **Parsing**
  - Parse `SKILL.md` frontmatter + body.
  - Provide a stable `SkillProperties` model (name/description/license/compatibility/metadata/allowed_tools).
- **Validation**
  - Validate required files and basic folder layout.
  - Provide deterministic “available skills” prompt text (prefer spec-style `<available_skills>...</available_skills>`).
- **Packaging**
  - `pack_skill_dir(...) -> .skill` zip (convention)
  - `unpack_skill_zip(...) -> dir`
- **Loaders**
  - `FilesystemSkillLoader` (project + user scopes; precedence rules)
  - `RemoteSkillLoader` (fetch by id/version from a gateway API)

Why a separate package:
- Keeps `abstractcore`/`abstractruntime` lean.
- Lets UIs/hosts (AbstractCode, AbstractAssistant, web) share identical semantics.

### B) `abstractagent` (agent patterns)

Add a **skill-aware prompt builder** while keeping “logic stays runtime-agnostic”:

- Extend adapters to optionally inject *only* a compact “available skills” metadata block into the system prompt.
- Support “activation” as an explicit step (user-invoked first; model-invoked later).
- If we add a model-invoked path, define a **schema-only built-in tool** (e.g., `open_skill`) so the runtime/host executes the read and logs it.

### C) `abstractruntime` (durable execution + ledger)

Add a runtime-owned integration point so skill loading/activation is durable and observable:

- Provide a runtime-owned tool/effect handler for reading skill content by `(skill_id, version, path?)` that:
  - stores full SKILL.md content as an artifact (or returns it if small),
  - appends a ledger record for “skill activated/read”,
  - enforces limits (max bytes, max refs) and emits `#FALLBACK`/`#TRUNCATION` as needed.
- Add a small policy hook that merges a skill’s `allowed-tools` into `_runtime.allowed_tools` (intersection, not union) when present.

### D) `abstractgateway` (distribution + multi-client)

Add a **skills registry** parallel to the existing WorkflowBundles (`.flow`) registry:

- Storage: `<data_dir>/skills/` (folders and/or `.skill` zips), with a small index file.
- API:
  - list skills (metadata-only)
  - fetch skill content/resources on demand
  - install/update/deprecate skills (admin endpoints; auth-protected)
- Thin-client support: include skills metadata in discovery endpoints so UIs can show “available skills” without fetching full bodies.

### E) Optional: `abstractmemory` + `abstractsemantics`

Later, add “skills search” and governance:

- Store skill metadata + embeddings in AbstractMemory for semantic lookup and recommendations.
- Use AbstractSemantics to standardize skill categories/tags if you want “approved skill taxonomy”.

## Phased delivery plan

### Phase 0 — ADR + minimal core utilities (1–2 weeks)

Deliverables:
- ADR: “Agent Skills integration in AbstractFramework”
  - define goals/non-goals, security posture, default discovery paths, and what “activation” means.
- New package `abstractskills` (or a minimal module under `abstractcore` if you want fewer repos)
  - parse SKILL.md, expose `SkillProperties`, validate folder, compile metadata prompt block.
- Unit tests for parsing/validation (no runtime/gateway changes yet).

Decisions to lock:
- Skill identity:
  - spec-level identity is the skill `name` (must match the leaf directory name)
  - AbstractFramework may optionally add an external namespace/source dimension (e.g., multiple skill roots or gateway registry) to avoid collisions
- Skills ↔ flows contract:
  - run-attached skills are the primary mechanism
  - `.flow` bundles may declare dependencies in `manifest.metadata`
  - bundle-embedded skills (assets) is optional and can be deferred
- Default skill search paths:
  - user: `~/.abstractframework/skills/`
  - project: `.abstractframework/skills/`
  - plus an explicit CLI override list

### Phase 1 — Local skills in host apps (metadata + user-invoked activation) (1–2 weeks)

Target: AbstractCode + AbstractAssistant (local-host mode).

Deliverables:
- “Skills discovery” in the host process:
  - scan default paths; load only properties (`name`/`description`/optional metadata).
  - show skills in `/help` or a dedicated command (`/skills`).
- User-invoked activation:
  - `/skill <name>` loads full SKILL.md and injects it (or a summarized form) into the next agent cycle.
  - activation is **explicit** (no model-invoked loading yet).

Guardrails:
- Hard cap on metadata per skill + total skills injected.
- No `scripts/` execution in this phase; if present, display “requires enablement” with `#FALLBACK`.

### Phase 2 — Durable activation + ledger logging + allowed-tools gating (2–3 weeks)

Target: AbstractRuntime + AbstractAgent integration.

Deliverables:
- Runtime-owned “skill activation/read” handler:
  - artifacts for skill bodies/resources
  - ledger record for activation and any resource reads
- Tool gating:
  - if a skill provides `allowed-tools`, enforce it at the runtime tool executor boundary
  - log any denied tool calls with `#FALLBACK` and actionable instruction

Why now:
- This is where skills become “first-class and auditable” rather than a prompt trick.

### Phase 3 — Gateway skills registry (distribution + thin-client UX) (3–5 weeks)

Target: AbstractGateway + web/thin clients.

Deliverables:
- Gateway skills registry:
  - scan `<flows_dir>/`-adjacent `skills/` OR a new `ABSTRACTGATEWAY_SKILLS_DIR`
  - install/update via `.skill` zip upload (admin-only)
  - deprecate/disable skills without deleting (keeps historical replay intact)
- APIs:
  - `GET /api/gateway/skills` (metadata)
  - `GET /api/gateway/skills/{id}` (skill body + index of resources)
  - `GET /api/gateway/skills/{id}/resources/{path}` (resource bytes)
- Thin clients:
  - show available skills list; allow activation by sending a durable command that updates run vars (or triggers a runtime effect).

### Phase 4 — Script execution (safe-by-default) (3–6 weeks)

Target: host tool execution + approvals + evidence.

Deliverables:
- Define a safe contract for skill scripts:
  - scripts run only via explicit tools (never “implicitly because a skill exists”)
  - require allowlisted tool names + explicit approvals (and/or a sandbox)
  - capture evidence/artifacts for outputs
- Provide a “skill tool adapter”:
  - map skill scripts to runtime tools (e.g., `skill.<skill_id>.<script_name>`) with stable schemas.

### Phase 5 — Advanced features + ecosystem compatibility (ongoing)

Optional enhancements once core value is proven:
- Claude Code extensions support (selectively):
  - `user-invocable`, `disable-model-invocation`, `argument-hint`
  - `context: fork` (maps well to runtime subworkflows)
  - hooks (pre/post) as explicit, durable nodes/effects
- Skill search:
  - index skill metadata in AbstractMemory; add a “recommend skills” tool.
- Provider-specific integration:
  - Optional AbstractCore integration for Anthropic “container skills” (behind an extra and explicit config).

## Open questions (resolve in Phase 0 ADR)

- Skill id/version semantics: do we require semantic versions, or use content hashes?
- Where does “active skills” live in the durable model: `context`, `scratchpad`, or `_runtime`?
- Do we ever want a first-class `manifest.skills` field (instead of `manifest.metadata.skills`) for bundle-declared dependencies?
- Authoring UX for bundle-declared dependencies:
  - VisualFlow JSON currently has no `metadata` field; the gateway publish path auto-generates manifest metadata.
  - If we want authors to declare skill dependencies via manifests, we must add an authoring surface (CLI metadata,
    Flow Editor fields, or extend VisualFlow schema to carry an optional metadata object).
- Multi-tenant gateway policy:
  - who can install skills, who can activate, and how to audit skill usage?

--- docs/skills/claude-agent-skills-overview.md ---
# Claude Shareable Skills Overview (Agent Skills) — Feb 2026

## What “Skills” Means Here
This report covers **shareable Agent Skills**: portable, model-agnostic skill packs
defined by the **Agent Skills open standard** and used in Claude (Claude.ai, Claude Code,
and Claude API). These are *not* intrinsic model capabilities; they are **files and folders**
that specialize an agent’s behavior.

Primary definitions:
- Agent Skills are “folders of instructions, scripts, and resources” that agents can discover
  and use to perform tasks more accurately and efficiently.  
  Source: https://agentskills.io/what-are-skills.md
- Anthropic’s skills repository is an implementation of this standard for Claude.  
  Source: https://raw.githubusercontent.com/anthropics/skills/main/README.md

## Core Structure (How Skills Are Packaged)
An Agent Skill is a directory with a required `SKILL.md` and optional resources:
```
my-skill/
├── SKILL.md        # required: YAML frontmatter + instructions
├── scripts/        # optional: executable code
├── references/     # optional: on-demand docs
└── assets/         # optional: templates/resources
```
Sources:
- https://agentskills.io/what-are-skills.md
- https://agentskills.io/specification.md

### SKILL.md Format
`SKILL.md` includes:
- YAML frontmatter (required): `name`, `description`
- Markdown body: instructions and workflow details  
Source: https://agentskills.io/specification.md

## How Skills Work (High-Level)
Agent Skills use **progressive disclosure**:
1. **Discovery**: Only `name` and `description` are loaded at startup.
2. **Activation**: Full `SKILL.md` is loaded when relevant.
3. **Execution**: Optional scripts/resources are accessed as needed.  
Sources:
- https://agentskills.io/what-are-skills.md
- https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills

This keeps context small while enabling rich, on-demand specialization.

## How Skills Are Used In Claude Code
Claude Code implements the Agent Skills standard and extends it with:
- **Slash commands**: `/skill-name` invokes a skill directly.
- **Invocation control**: `disable-model-invocation` and `user-invocable` frontmatter.
- **Allowed tools**: `allowed-tools` to restrict or pre-approve tool use.
- **Subagents**: `context: fork` to run a skill in a dedicated subagent.
- **Dynamic context injection**: `!` command execution inside skill content.  
Source: https://code.claude.com/docs/en/skills

### Skill Locations In Claude Code
Claude Code loads skills from specific directories:
- Personal: `~/.claude/skills/`
- Project: `.claude/skills/`
- Enterprise-managed settings
- Plugins (skill packs in plugin directories)  
Source: https://code.claude.com/docs/en/skills

## How Skills Are Used In Claude API
The Claude API supports skills as **containers** combined with **code execution**:
- Skills are attached in the `container.skills` parameter.
- Types: `anthropic` (pre-built) or `custom` (uploaded).
- Versions can be pinned or set to `latest`.
- Requires beta headers and the code execution tool.  
Source: https://docs.claude.com/en/api/skills-guide

## How Skills Are Shared
Skills are shareable because they are just folders/files:
- **GitHub repos** and **plugin marketplaces** for discovery.
- **Version control** for team sharing (commit `.claude/skills/`).
- **Claude API Skills** allow uploading custom skills.  
Sources:
- https://raw.githubusercontent.com/anthropics/skills/main/README.md
- https://code.claude.com/docs/en/skills
- https://docs.claude.com/en/api/skills-guide

## Key Takeaways
- Skills are portable, model-agnostic, and *not tied to Claude only*.
- They enable **specialization** by bundling procedural knowledge and scripts.
- Claude Code and Claude API provide first‑party implementations and distribution paths.


--- docs/skills/claude-agent-skills-top-20.md ---
# Top 20 Shareable Claude Skills (Feb 2026)

Selection method:
- **16 skills** from Anthropic’s official `anthropics/skills` repository
- **4 canonical example skills** from Claude Code documentation (shareable, SKILL.md‑based)
This yields 20 widely cited, shareable skills as of Feb 2026.

## 1) `docx` — Word Documents
- **What:** Create/read/edit Word documents with formatting, tables, images, and tracked changes.
- **How:** Uses docx-js and XML edit workflows; provides detailed rules and scripts.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/docx/SKILL.md

## 2) `pdf` — PDF Processing
- **What:** Extract, merge, split, OCR, watermark, and create PDF files.
- **How:** Uses pypdf/pdfplumber/reportlab plus CLI tools and optional forms guide.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/pdf/SKILL.md

## 3) `pptx` — Presentation Creation/Editing
- **What:** Create or edit slide decks with strong layout and QA guidance.
- **How:** Uses markitdown for extraction; pptxgenjs or template editing; QA loop.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/pptx/SKILL.md

## 4) `xlsx` — Spreadsheet Modeling
- **What:** Create and edit spreadsheets with formulas, formatting, and recalculation.
- **How:** Uses pandas/openpyxl with a strict formula recalculation workflow.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/xlsx/SKILL.md

## 5) `webapp-testing` — Playwright UI Testing
- **What:** Test local web apps, take screenshots, and validate UI behavior.
- **How:** Playwright scripts plus helper server lifecycle scripts.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/webapp-testing/SKILL.md

## 6) `web-artifacts-builder` — Advanced HTML Artifacts
- **What:** Build complex Claude.ai artifacts with React/Tailwind/shadcn.
- **How:** Init project, build, then bundle into a single HTML artifact.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/web-artifacts-builder/SKILL.md

## 7) `frontend-design` — UI Design + Code
- **What:** Produce distinctive, production‑grade frontend UI.
- **How:** Strong aesthetic rules + real HTML/CSS/JS or framework code.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/frontend-design/SKILL.md

## 8) `algorithmic-art` — Generative p5.js Art
- **What:** Create algorithmic art and interactive HTML artifacts.
- **How:** Define a generative “philosophy” then implement in p5.js.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/algorithmic-art/SKILL.md

## 9) `canvas-design` — Visual Design Artifacts
- **What:** Create visual design output (PDF/PNG) from a design philosophy.
- **How:** Design manifest → render high‑craft visual work.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/canvas-design/SKILL.md

## 10) `theme-factory` — Theme Application
- **What:** Apply curated design themes (colors/fonts) to artifacts.
- **How:** Choose from pre‑set themes or generate a new one.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/theme-factory/SKILL.md

## 11) `brand-guidelines` — Anthropic Brand Styling
- **What:** Apply official Anthropic brand colors and typography.
- **How:** Prescriptive palette and font rules.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/brand-guidelines/SKILL.md

## 12) `internal-comms` — Internal Communications
- **What:** Produce 3P updates, newsletters, FAQs, and status reports.
- **How:** Select format from examples and follow structured guidelines.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/internal-comms/SKILL.md

## 13) `doc-coauthoring` — Doc Co‑Authoring Workflow
- **What:** Guided multi‑stage workflow for technical docs and specs.
- **How:** Context gathering → structured drafting → reader testing.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/doc-coauthoring/SKILL.md

## 14) `mcp-builder` — MCP Server Builder
- **What:** Build MCP servers with best‑practice tool design.
- **How:** Phased workflow with references for MCP SDKs and evaluation.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md

## 15) `skill-creator` — Skill Authoring Guide
- **What:** Build new skills with proper structure and packaging.
- **How:** Progressive disclosure guidance, packaging scripts, and best practices.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/skill-creator/SKILL.md

## 16) `slack-gif-creator` — Slack GIFs
- **What:** Create Slack‑optimized GIFs and animations.
- **How:** Python/PIL workflow with helper utilities and validation.
- **Source:** https://raw.githubusercontent.com/anthropics/skills/main/skills/slack-gif-creator/SKILL.md

## 17) `deploy` — Manual Deployment Workflow (Example)
- **What:** A manually‑invoked deployment checklist.
- **How:** `disable-model-invocation: true` ensures only user can run it.
- **Source:** https://code.claude.com/docs/en/skills

## 18) `safe-reader` — Read‑Only Mode (Example)
- **What:** Restrict Claude to safe, read‑only tools.
- **How:** Use `allowed-tools` to limit tool access within the skill.
- **Source:** https://code.claude.com/docs/en/skills

## 19) `pr-summary` — Dynamic PR Summaries (Example)
- **What:** Summarize pull requests using live CLI data.
- **How:** `!` command injection runs shell commands before the prompt.
- **Source:** https://code.claude.com/docs/en/skills

## 20) `deep-research` — Subagent Research (Example)
- **What:** Launch a forked research subagent with isolated context.
- **How:** `context: fork` and `agent: Explore` run the skill in a subagent.
- **Source:** https://code.claude.com/docs/en/skills


--- docs/skills/claude-agent-skills-sources.md ---
# Claude Agent Skills Sources (Accessed Feb 2026)

## Agent Skills Standard
- Overview: https://agentskills.io/what-are-skills.md
- Specification: https://agentskills.io/specification.md
- Integration guide: https://agentskills.io/integrate-skills.md
- Standard repo: https://raw.githubusercontent.com/agentskills/agentskills/main/README.md

## Anthropic Engineering
- Agent Skills overview and progressive disclosure:
  https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills

## Anthropic Skills Repository (Official Examples)
- Repository overview:
  https://raw.githubusercontent.com/anthropics/skills/main/README.md

### SKILL.md sources (official examples)
- Algorithmic art:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/algorithmic-art/SKILL.md
- Brand guidelines:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/brand-guidelines/SKILL.md
- Canvas design:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/canvas-design/SKILL.md
- Doc coauthoring:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/doc-coauthoring/SKILL.md
- DOCX:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/docx/SKILL.md
- Frontend design:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/frontend-design/SKILL.md
- Internal comms:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/internal-comms/SKILL.md
- MCP builder:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md
- PDF:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/pdf/SKILL.md
- PPTX:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/pptx/SKILL.md
- Skill creator:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/skill-creator/SKILL.md
- Slack GIF creator:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/slack-gif-creator/SKILL.md
- Theme factory:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/theme-factory/SKILL.md
- Web artifacts builder:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/web-artifacts-builder/SKILL.md
- Webapp testing:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/webapp-testing/SKILL.md
- XLSX:
  https://raw.githubusercontent.com/anthropics/skills/main/skills/xlsx/SKILL.md

## Claude Code Skills Documentation
- Skills overview and examples:
  https://code.claude.com/docs/en/skills

## Claude API Skills Guide
- Skills + container usage + code execution:
  https://docs.claude.com/en/api/skills-guide

## Notes
- The Claude Help Center articles for skills were not accessible via the fetch tool.
- This report relies on official Anthropic and Agent Skills standard sources only.


--- docs/skills/agent-skills-ecosystem-scan.md ---
# Agent Skills Ecosystem Scan — Additional High-Value Skills (Feb 2026)

## Purpose
Continue the online search for **shareable Agent Skills** beyond Anthropic’s public repo and identify additional skill packs that could be high value for AbstractFramework.

## Methodology + Limits
- **Primary sources**: curated ecosystem lists and public GitHub repositories that publish `SKILL.md`.
- **Repository inspection**: read `SKILL.md` files directly for concrete scope and behavior.
- **Limitations**: GitHub code search API requires authentication (401). I used repository search + curated lists instead of code search.

## Additional Skill Libraries (Beyond Anthropic)

### 1) Vercel — Frontend performance + UI quality
Vercel publishes a curated skill pack with concrete UI/React guidance:
- **React Best Practices**: 57 performance rules for React/Next.js.  
  Source: https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/react-best-practices/SKILL.md
- **React Composition Patterns**: guidance for scalable component APIs.  
  Source: https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/composition-patterns/SKILL.md
- **React Native Skills**: performance and UI patterns for mobile apps.  
  Source: https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/react-native-skills/SKILL.md
- **Web Design Guidelines**: UI review with external rule fetch.  
  Source: https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/web-design-guidelines/SKILL.md

### 2) HashiCorp — Terraform/IaC workflows
HashiCorp’s pack focuses on Terraform generation and module design:
- **Terraform Style Guide**: code organization + security rules.  
  Source: https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/code-generation/skills/terraform-style-guide/SKILL.md
- **Refactor Module**: monolith → reusable module workflow.  
  Source: https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/module-generation/skills/refactor-module/SKILL.md
- **Run Acceptance Tests**: structured provider acceptance testing flow.  
  Source: https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/provider-development/skills/run-acceptance-tests/SKILL.md

### 3) Trail of Bits — Security scanning + triage
Trail of Bits publishes a security-centric skill library with tooling guidance:
- **CodeQL**: structured database build + analysis workflow.  
  Source: https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/codeql/SKILL.md
- **Semgrep**: multi-agent scan + triage workflow with hard approval gates.  
  Source: https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/semgrep/SKILL.md
- **SARIF Parsing**: process and aggregate scan results.  
  Source: https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/sarif-parsing/SKILL.md

### 4) OWASP Security Skill — Code review checklist
OWASP/ASVS-based security review guidance:
- **OWASP Security**: Top 10:2025 + ASVS 5.0 + agentic AI security checklist.  
  Source: https://raw.githubusercontent.com/agamm/claude-code-owasp/main/.claude/skills/owasp-security/SKILL.md

### 5) Varlock — Secrets hygiene
Skill focused on preventing secrets from leaking to logs or context:
- **Varlock**: safe environment variable handling rules.  
  Source: https://raw.githubusercontent.com/wrsmith108/varlock-claude-skill/main/skills/varlock/SKILL.md

### 6) Superpowers — Engineering process discipline
Reusable procedural skills for safer engineering workflows:
- **Test-Driven Development**  
  Source: https://raw.githubusercontent.com/obra/superpowers/main/skills/test-driven-development/SKILL.md
- **Systematic Debugging**  
  Source: https://raw.githubusercontent.com/obra/superpowers/main/skills/systematic-debugging/SKILL.md

### 7) Product/PM Skills — Problem framing and delivery
PM-oriented skills for better specification and experimentation:
- **Problem Statement**  
  Source: https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/define-problem-statement/SKILL.md
- **PRD**  
  Source: https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/deliver-prd/SKILL.md
- **Experiment Design**  
  Source: https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/measure-experiment-design/SKILL.md

### 8) Ecosystem discovery infrastructure
Curated lists and skill discovery tooling:
- **Awesome Claude Skills** (curated directory of skill packs).  
  Source: https://raw.githubusercontent.com/BehiSecc/awesome-claude-skills/main/README.md
- **Claude Skills MCP server** (vector search of skills).  
  Source: https://github.com/K-Dense-AI/claude-skills-mcp

## High-Value Skill Categories For AbstractFramework
These categories are likely high value based on the framework’s durable runtime, tool approval boundaries, gateway-first distribution, and observability model (see architecture deep dive notes).

1) **Security review + static analysis**
   - CodeQL, Semgrep, SARIF parsing, OWASP security checklists.
   - These align with durable runs, ledger evidence, and tool gating.

2) **Infrastructure / IaC workflows**
   - Terraform style guide + module refactoring skills.
   - Good fit for deterministic workflows and repeatable automation.

3) **Secrets and environment hygiene**
   - Varlock skill prevents sensitive data leakage.
   - Maps to AbstractFramework’s explicit tool approval boundaries.

4) **Engineering process rigor**
   - TDD + systematic debugging skills.
   - Fits agentic workflows and helps ensure safe, repeatable changes.

5) **Product/specification quality**
   - Problem statements, PRDs, experiment design.
   - Useful for SmartNote ingestion and workflow-driven documentation.

6) **Frontend performance + UX review**
   - Vercel React and UI guideline skills.
   - Helpful for AbstractCode usage and code review flows.

## Suggested Next Research Steps
- Deep-scan curated lists for additional domain skills (DevOps, data engineering, compliance).
- Evaluate skill packaging formats in each repo (compatibility + allowed-tools usage).
- Track skills that already embed MCP usage (for compatibility with AbstractRuntime tool gating).

## Sources Index
See `docs/skills/agent-skills-ecosystem-sources.md` for the complete list of sources.

--- docs/skills/agent-skills-ecosystem-sources.md ---
# Agent Skills Ecosystem Sources — Feb 2026

## Curated Lists / Discovery
- Awesome Claude Skills (curated list):  
  https://raw.githubusercontent.com/BehiSecc/awesome-claude-skills/main/README.md
- Claude Skills MCP server (skill search MCP):  
  https://github.com/K-Dense-AI/claude-skills-mcp

## Vercel Agent Skills
- React Best Practices:  
  https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/react-best-practices/SKILL.md
- React Composition Patterns:  
  https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/composition-patterns/SKILL.md
- React Native Skills:  
  https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/react-native-skills/SKILL.md
- Web Design Guidelines:  
  https://raw.githubusercontent.com/vercel-labs/agent-skills/main/skills/web-design-guidelines/SKILL.md

## HashiCorp Agent Skills (Terraform)
- Terraform Style Guide:  
  https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/code-generation/skills/terraform-style-guide/SKILL.md
- Refactor Module:  
  https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/module-generation/skills/refactor-module/SKILL.md
- Run Acceptance Tests:  
  https://raw.githubusercontent.com/hashicorp/agent-skills/main/terraform/provider-development/skills/run-acceptance-tests/SKILL.md

## Trail of Bits Skills (Security)
- CodeQL skill:  
  https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/codeql/SKILL.md
- Semgrep skill:  
  https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/semgrep/SKILL.md
- SARIF parsing skill:  
  https://raw.githubusercontent.com/trailofbits/skills/main/plugins/static-analysis/skills/sarif-parsing/SKILL.md

## OWASP / Security
- OWASP security skill:  
  https://raw.githubusercontent.com/agamm/claude-code-owasp/main/.claude/skills/owasp-security/SKILL.md

## Secrets / Environment Hygiene
- Varlock skill:  
  https://raw.githubusercontent.com/wrsmith108/varlock-claude-skill/main/skills/varlock/SKILL.md

## Engineering Process
- Test-Driven Development skill:  
  https://raw.githubusercontent.com/obra/superpowers/main/skills/test-driven-development/SKILL.md
- Systematic Debugging skill:  
  https://raw.githubusercontent.com/obra/superpowers/main/skills/systematic-debugging/SKILL.md

## Product / PM Skills
- Problem Statement skill:  
  https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/define-problem-statement/SKILL.md
- PRD skill:  
  https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/deliver-prd/SKILL.md
- Experiment Design skill:  
  https://raw.githubusercontent.com/product-on-purpose/pm-skills/main/skills/measure-experiment-design/SKILL.md

--- docs/skills/abstractframework-agent-skills-fit.md ---
# AbstractFramework Fit Analysis — Shareable Agent Skills (Feb 2026)

## Executive Fit Summary
AbstractFramework **can benefit significantly** from Agent Skills because the format is
model‑agnostic, portable, and aligns with the framework’s goals: **durability, observability,
and modularity**. Skills are not a replacement for AbstractFlow, but a lightweight, shareable
layer for procedural knowledge and tool workflows.

Sources for skill behavior and format:
- https://agentskills.io/what-are-skills.md
- https://agentskills.io/specification.md
- https://code.claude.com/docs/en/skills
- https://docs.claude.com/en/api/skills-guide
- https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills

## Where AbstractFramework Benefits (Why + How)

### 1) Add Agent Skills Support To AbstractCode/Assistant
**Why:** Users can import Claude/Cursor/Codex‑style skills (portable SKILL.md packs) without
rewriting workflows. This makes AbstractCode more interoperable.

**How:** Implement a skills loader that:
- Discovers `SKILL.md` folders (project + user scopes).
- Injects `name`/`description` into system prompt (metadata only).
- Loads full `SKILL.md` on activation (progressive disclosure).
- Supports optional `allowed-tools` to enforce tool gating.

**Justification:** This mirrors the Agent Skills spec and Claude Code behavior
(`name`/`description` metadata + on‑demand skill loading).  
Sources: https://agentskills.io/what-are-skills.md, https://code.claude.com/docs/en/skills

### 2) Skill Registry In AbstractGateway
**Why:** The Gateway already distributes workflows; a skills registry enables organization‑wide
sharing of reusable procedural knowledge across all clients.

**How:** Add a skills registry parallel to `.flow` bundles:
- Store skills in a dedicated directory or artifact store.
- Provide an API for listing, enabling, and versioning skills.
- Broadcast skill metadata to thin clients for discovery.

**Justification:** Skills are portable folders; gateway distribution fits the existing architecture.

### 3) Tool Approval Integration Via `allowed-tools`
**Why:** Skills can explicitly list approved tools. This maps directly to AbstractRuntime’s
tool approval boundaries and audit trail.

**How:** When a skill is activated, merge `allowed-tools` with the tool policy for that run.
If a tool is outside the allowlist, require approval and emit `#FALLBACK`.

**Justification:** Agent Skills spec supports `allowed-tools` (experimental) and Claude Code
uses it for permissions.  
Sources: https://agentskills.io/specification.md, https://code.claude.com/docs/en/skills

### 4) Skill Execution Logging In The Ledger
**Why:** Skills are procedural knowledge; their activation and resource use should be auditable.

**How:** Record:
- Skill name/version on activation
- Files/scripts read or executed
- Any outputs or generated artifacts

**Justification:** Matches AbstractFramework’s observability and provenance model.

### 5) Support For `.skill` Packaging
**Why:** Shareable skills need a portable format for teams. The skill‑creator workflow in the
Anthropic repo uses a `.skill` package (zip). Supporting this improves interoperability.

**How:** Add a CLI helper to package/unpackage skills and validate against the spec.

**Justification:** Skills are file‑based; packaging enables controlled distribution and versioning.

### 6) Optional Anthropic Skills API Integration
**Why:** Some Anthropic skills (docx/pdf/pptx/xlsx) are server‑hosted and usable via the API.

**How:** Extend AbstractCore’s Anthropic provider to expose `container.skills` and
code execution when configured. Track skill metadata in the run state.

**Justification:** This is provider‑specific but valuable for users who want
Anthropic‑hosted skills without manual setup.  
Source: https://docs.claude.com/en/api/skills-guide

## Skills That Are Already Covered (Low Incremental Value)
- **Tool calling, MCP, and structured output** already exist in AbstractCore.
- **Durable workflows** are stronger than skills for complex multi‑agent orchestration.

Skills add value primarily as **portable procedural knowledge packs** and
as a compatibility layer with other agent ecosystems.

## Risks And Guardrails
- **Script execution risk:** Skills can include scripts; require sandboxing and explicit
  approvals. If disabled, emit `#FALLBACK`.
- **Context bloat:** Too many skills can overload the prompt; enforce metadata limits and
  avoid loading full skills unless activated.
- **Environment mismatch:** Respect the `compatibility` field; if requirements are unmet,
  warn with `#FALLBACK`.
- **Truncation:** If any skill content must be truncated, label `#TRUNCATION` with reason.

## ADR Recommendation
Create an ADR: **“Agent Skills Support in AbstractFramework”** covering:
- Skill discovery paths and registry model
- Tool approval and sandbox policy
- Ledger/provenance logging for skill activation
- `.skill` packaging support
- Provider‑specific API integration (Anthropic containers)

--- docs/skills/abstractframework-architecture-deep-dive.md ---
# AbstractFramework Architecture Deep Dive — Notes (Feb 2026)

## Scope
This note summarizes the **implemented architecture** across core packages and UIs, based on the official architecture docs in each repo. The goal is to ground any skills recommendations in real constraints.

## System-Level Architecture
AbstractFramework is designed around **durable, observable execution** with a **gateway-first** deployment path (recommended) and a **local in-process** path (alternative).  
Source: `docs/architecture.md`

Key implications:
- Every run is **durable** (explicit waits, restart-safe).
- Every step is **recorded** in an append-only ledger (replay-first UI).
- Tool execution happens at explicit **durable boundaries**.

## Core Invariants (Non-Negotiable)
- **Run state is JSON-safe**; large payloads must be stored as artifacts.  
  Source: `abstractruntime/docs/architecture.md`
- **Ledger is append-only** (hash-chained in some stores); it is the source of truth.  
  Source: `docs/architecture.md`, `abstractruntime/docs/architecture.md`
- **Tool schemas are durable; tool callables are not** (host executes tools after approval).  
  Source: `docs/architecture.md`, `abstractassistant/docs/architecture.md`, `abstractcode/docs/architecture.md`

## Foundation Layer

### AbstractCore (LLM + tools + media)
AbstractCore provides provider-agnostic LLM access, tool schema normalization, and media handling.  
Source: `abstractcore/docs/architecture.md`

Notable capabilities:
- Multi-provider factory (`create_llm`) and consistent interface.
- Tool-call parsing and tag-rewriting for provider compatibility.
- Unified streaming with incremental tool detection.
- Optional capability plugins (voice, vision, music) discovered via entry points.

### AbstractRuntime (durable execution kernel)
AbstractRuntime is the durable workflow engine.  
Source: `abstractruntime/docs/architecture.md`

Notable capabilities:
- `WorkflowSpec` nodes -> `StepPlan` effects.
- Explicit waits (`ASK_USER`, `WAIT_EVENT`, `WAIT_UNTIL`, `TOOL_CALLS`).
- Durable stores (RunStore, LedgerStore, ArtifactStore, Snapshots).
- Workflow bundles (`.flow`) and VisualFlow compiler integration.

## Composition Layer

### AbstractAgent (ReAct / CodeAct / MemAct)
Agent patterns are expressed as runtime workflows with strict namespaces and tool gating.  
Source: `abstractagent/docs/architecture.md`

Key design:
- Logic is runtime-agnostic; adapters wire to AbstractRuntime.
- Tool allowlists are stored in `_runtime.allowed_tools`.
- CodeAct supports fenced python execution as an explicit tool.

### AbstractFlow (VisualFlow + bundles)
AbstractFlow is the authoring layer for VisualFlow workflows and bundles.  
Source: `abstractflow/docs/architecture.md`

Key design:
- VisualFlow JSON is portable and executes in any host.
- `.flow` bundles package VisualFlow graphs + manifest + subflows.
- Session runners support event-driven flows (`on_event` → child workflows).

## Control Plane

### AbstractGateway (durable run gateway)
The gateway provides HTTP/SSE APIs for run control, ledger replay, scheduling, and security.  
Source: `abstractgateway/docs/architecture.md`

Key design:
- Replay-first ledger streaming (SSE is an optimization).
- Runner loop processes durable commands and ticks runs.
- Split-process deployment supported (API + runner).

## Clients and Hosts

### AbstractCode (CLI/TUI + web thin client)
Local CLI is a **host** (runs runtime + tools locally).  
Web app is a **thin client** that talks to the gateway.  
Source: `abstractcode/docs/architecture.md`

### AbstractAssistant (local host)
Tray UI runs AbstractAgent + AbstractRuntime locally; tools executed after approval.  
Source: `abstractassistant/docs/architecture.md`

### AbstractObserver (gateway-only UI)
UI renders by ledger replay + SSE; submits durable commands to gateway.  
Source: `abstractobserver/docs/architecture.md`

### SmartNote (thin client + durable backend)
SmartNote server runs chunked ingestion workflows and writes KG assertions.  
Source: `smartnote/docs/architecture.md`

## Memory and Semantics

### AbstractMemory (temporal triple store)
Stores append-only, provenance-aware triples with deterministic query semantics.  
Source: `abstractmemory/docs/architecture.md`

### AbstractSemantics (registry + schema)
Provides registry of predicates/types + JSON schema builder for KG assertions.  
Source: `abstractsemantics/docs/architecture.md`

## Observability and Evidence
Evidence is an explicit concept: ledger + artifacts + snapshots + history bundles.  
Sources: `docs/architecture.md`, `abstractruntime/docs/architecture.md`

## Implications for Skill Integration (Constraints)
These constraints must be respected by any skills proposal:
- **Durability**: skills should not rely on ephemeral in-memory state.
- **Tool boundary**: tools must remain host-executed with durable waits.
- **Replay-first**: skill activation and outputs should be ledger-recorded.
- **No silent fallbacks**: degraded paths must emit `#FALLBACK` warnings (project policy).

## References (Architecture Docs Used)
- `docs/architecture.md`
- `abstractcore/docs/architecture.md`
- `abstractruntime/docs/architecture.md`
- `abstractagent/docs/architecture.md`
- `abstractflow/docs/architecture.md`
- `abstractgateway/docs/architecture.md`
- `abstractcode/docs/architecture.md`
- `abstractassistant/docs/architecture.md`
- `abstractobserver/docs/architecture.md`
- `abstractmemory/docs/architecture.md`
- `abstractsemantics/docs/architecture.md`
- `smartnote/docs/architecture.md`

--- docs/claude/README.md ---
# Claude research notes (versioned)

This folder contains **versioned research notes** about Claude capabilities/skills (distinct from the shareable Agent
Skills `SKILL.md` ecosystem).

Related:
- Agent Skills (shareable `SKILL.md`) notes live in `docs/skills/`
- Agent Skills integration proposal: `docs/guide/agent-skills.md`

Files:
- `docs/claude/claude-skills-overview.md`
- `docs/claude/claude-skills-top-20.md`
- `docs/claude/claude-skills-sources.md`
- `docs/claude/abstractframework-fit.md`


--- docs/claude/claude-skills-overview.md ---
# Claude Skills Research Overview (Feb 2026)

## Definition
A "Claude skill" here means any publicly documented capability of Claude models or the Claude
developer platform (API + tools + claude.ai features) that enables users to perform a class of
tasks. This includes model-level capabilities (reasoning, vision, long-context) and platform
capabilities (tool use, web search/fetch, computer use, artifacts, memory).

## Sources And Scope
This overview is based on Anthropic’s public documentation and product announcements available
as of February 2026. See `untracked/skills/claude-skills-sources.md` for the full list of sources.

Key references include:
- “Building with Claude” (capabilities overview, tool use, vision, long context)  
  https://docs.anthropic.com/claude/docs/overview
- Tool use docs (client tools, server tools, strict tool use, MCP)  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview
- Computer use tool (desktop automation, agent loop, thinking param)  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool
- Web search tool (citations, dynamic filtering with code execution)  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-search-tool
- Web fetch tool (page/PDF fetch, citations, dynamic filtering)  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-fetch-tool
- Claude model announcements (reasoning, vision, long context, artifacts, memory)  
  https://www.anthropic.com/news/claude-3-family  
  https://www.anthropic.com/news/claude-3-5-sonnet  
  https://www.anthropic.com/news/claude-sonnet-4-6

## How Claude Skills Work (High-Level)
1. **Model capabilities**  
   Claude’s core skills (reasoning, writing, coding, multilingual, vision) are model-level
   capabilities described in the model announcements and overview docs. These are accessed
   through the standard Messages API.  
   References: https://docs.anthropic.com/claude/docs/overview,  
   https://www.anthropic.com/news/claude-3-family

2. **Tool use (function calling)**  
   Claude can emit structured tool calls based on a schema you provide. The API returns
   `tool_use` blocks, your app executes them, then sends `tool_result` blocks back. This
   enables deterministic integration with external systems.  
   Reference: https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

3. **Client tools vs server tools**  
   - **Client tools** run on your infrastructure (custom tools, computer use, bash, text editor).  
   - **Server tools** run on Anthropic’s infrastructure (web search, web fetch), with results
     embedded back into Claude’s response.  
   Reference: https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

4. **Agent loop for multi-step tasks**  
   Claude can repeatedly request tool actions and consume results until a task completes.
   This “agent loop” is central to computer use and multi-step automation.  
   Reference: https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool

5. **Server-side grounding and citations**  
   Web search and fetch tools provide citations, and can dynamically filter content using
   code execution to reduce token usage and improve relevance.  
   References:  
   https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-search-tool  
   https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-fetch-tool

6. **Reasoning transparency and long-horizon context**  
   Some models support “thinking” parameters (a dedicated reasoning budget) and context
   compaction to extend effective context for long-running tasks.  
   References:  
   https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool  
   https://www.anthropic.com/news/claude-sonnet-4-6

7. **Product-layer skills (claude.ai)**  
   Features like Artifacts and Memory are positioned as collaboration and personalization
   features inside the Claude product experience.  
   References:  
   https://www.anthropic.com/news/claude-3-5-sonnet  
   https://www.anthropic.com/news/claude-sonnet-4-6

## Interpretation Notes
- Some skills are **model capabilities** (intrinsic) while others are **platform features**
  (API tools or claude.ai UX). This report distinguishes them explicitly.
- Several features are in **beta** (e.g., computer use) and carry additional security and
  privacy constraints documented by Anthropic.
- Where a feature is announced but not fully specified (e.g., Memory in early announcements),
  this report documents only what is explicitly stated by Anthropic.


--- docs/claude/claude-skills-top-20.md ---
# Claude Top 20 Skills (As Of Feb 2026)

This list curates the most impactful Claude skills based on Anthropic documentation and
announcements. Each entry includes what the skill is, how it works (high-level), and evidence.

## 1) Text Generation And Rewriting
- **What it is:** High-quality text creation (summaries, reports, support replies, creative writing).
- **How it works:** Standard Messages API prompts; model generates fluent text with instruction
  following and brand-voice control.
- **Evidence:** https://docs.anthropic.com/claude/docs/overview

## 2) Code Generation, Debugging, And Translation
- **What it is:** Write, edit, debug, and translate code across languages and codebases.
- **How it works:** Natural-language prompts + code context; often paired with tools for edits or execution.
- **Evidence:** https://www.anthropic.com/news/claude-3-family,  
  https://www.anthropic.com/news/claude-3-5-sonnet

## 3) Advanced Reasoning And Analysis
- **What it is:** Strong performance on reasoning, math, forecasting, and multi-step analysis.
- **How it works:** Model-level capability expressed through instruction-following and structured prompts.
- **Evidence:** https://docs.anthropic.com/claude/docs/overview,  
  https://www.anthropic.com/news/claude-3-family

## 4) Multilingual Fluency And Translation
- **What it is:** Accurate responses and translations across non-English languages.
- **How it works:** Same generation pipeline with multilingual training; usable for translation features.
- **Evidence:** https://docs.anthropic.com/claude/docs/overview,  
  https://www.anthropic.com/news/claude-3-family

## 5) Vision Understanding (Images, Charts, Diagrams)
- **What it is:** Analyze visual inputs like charts, photos, diagrams, and scanned documents.
- **How it works:** Multimodal inputs (image + text) processed by vision-capable Claude models.
- **Evidence:** https://docs.anthropic.com/claude/docs/overview,  
  https://www.anthropic.com/news/claude-3-family,  
  https://www.anthropic.com/news/claude-3-5-sonnet

## 6) Long-Context Processing (200K To 1M Tokens)
- **What it is:** Read and reason over very large document sets in a single request.
- **How it works:** Large context windows in Claude models; Sonnet 4.6 adds a 1M token context in beta.
- **Evidence:** https://www.anthropic.com/news/claude-3-family,  
  https://www.anthropic.com/news/claude-sonnet-4-6

## 7) Tool Use / Function Calling (Client Tools)
- **What it is:** Structured tool invocation to integrate with external systems.
- **How it works:** Provide tool schemas; Claude emits `tool_use` blocks; app executes and returns
  `tool_result` blocks.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

## 8) Strict Tool Use / Structured Outputs
- **What it is:** Schema-validated tool inputs for robust production integrations.
- **How it works:** Tool definitions can be marked `strict: true` to guarantee schema conformance.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

## 9) Parallel Tool Use
- **What it is:** Multiple independent tool calls in a single model response.
- **How it works:** Claude returns multiple `tool_use` blocks; client returns matching results in one turn.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

## 10) MCP Tool Integration And Connectors
- **What it is:** Use tools from MCP servers and connectors without custom adapters.
- **How it works:** MCP tool schemas are converted to Claude tool schemas; connectors can be used
  in Claude.ai and related products.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview,  
  https://www.anthropic.com/news/claude-sonnet-4-6

## 11) Web Search Tool (Grounded Research + Citations)
- **What it is:** Server-side web search with citations in responses.
- **How it works:** Claude triggers `web_search` server tool; results are injected with citations.
  Newer versions add dynamic filtering with code execution.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-search-tool

## 12) Web Fetch Tool (Full Page/PDF Retrieval)
- **What it is:** Fetch and analyze full web pages or PDFs with optional citations.
- **How it works:** Claude calls `web_fetch`; the server retrieves content, optionally filters
  it, and returns it to the model.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-fetch-tool

## 13) Computer Use (Desktop Automation)
- **What it is:** Operate a desktop environment via screenshots, mouse, and keyboard actions.
- **How it works:** A specialized computer-use tool emits action requests (click, type, screenshot);
  the client executes them in a sandboxed environment and returns results.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool

## 14) Multi-Step Agent Looping
- **What it is:** Iterative tool calling until a task is completed.
- **How it works:** Claude alternates between tool requests and tool results in a loop
  (“agent loop”) across multiple turns.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool,  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview

## 15) Thinking / Extended Thinking (Reasoning Budget)
- **What it is:** A controllable reasoning budget and optional visibility into the model’s
  reasoning process.
- **How it works:** A `thinking` parameter with a token budget is provided; the model returns
  reasoning traces and uses those tokens for deeper deliberation.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool,  
  https://www.anthropic.com/news/claude-sonnet-4-6

## 16) Prompt Caching
- **What it is:** Reuse cached context for faster, cheaper follow-ups.
- **How it works:** Clients add `cache_control` breakpoints; cached tool results and context are
  reused in subsequent requests.
- **Evidence:** https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-search-tool,  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-fetch-tool

## 17) Context Compaction
- **What it is:** Automatic summarization of older context to extend effective context length.
- **How it works:** As conversations approach limits, older context is compacted to preserve
  key information while freeing tokens.
- **Evidence:** https://www.anthropic.com/news/claude-sonnet-4-6

## 18) Artifacts (Interactive Workspace In Claude.ai)
- **What it is:** A dedicated workspace for generated code/documents alongside chat.
- **How it works:** Claude.ai renders outputs in a separate pane for editing and iterative work.
- **Evidence:** https://www.anthropic.com/news/claude-3-5-sonnet

## 19) Memory (Personalization / Long-Term Preferences)
- **What it is:** Persist user preferences and interaction history across sessions.
- **How it works:** Documented as a product feature; later announcements reference a memory tool.
- **Evidence:** https://www.anthropic.com/news/claude-3-5-sonnet,  
  https://www.anthropic.com/news/claude-sonnet-4-6

## 20) Safety And Prompt-Injection Defenses
- **What it is:** Guardrails to resist jailbreaks and prompt injection, especially in tool use.
- **How it works:** Model training plus classifier defenses; computer-use adds extra checks and
  may request user confirmation on risky steps.
- **Evidence:** https://docs.anthropic.com/claude/docs/overview,  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool


--- docs/claude/claude-skills-sources.md ---
# Claude Skills Sources (Accessed Feb 2026)

## Anthropic Documentation
- **Building with Claude (overview of capabilities)**  
  https://docs.anthropic.com/claude/docs/overview  
  Focus: high-level capabilities (text, code, vision, tool use), trust/safety positioning.

- **Tool use overview (client tools, server tools, strict tool use, MCP)**  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/overview  
  Focus: tool schemas, tool use flow, strict tool use, MCP integration.

- **Computer use tool (desktop automation + agent loop + thinking)**  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/computer-use-tool  
  Focus: computer-use tool actions, agent loop, security considerations, thinking parameter.

- **Web search tool (citations + dynamic filtering)**  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-search-tool  
  Focus: server-side search, citations, dynamic filtering with code execution, prompt caching.

- **Web fetch tool (page/PDF retrieval + citations)**  
  https://docs.anthropic.com/claude/docs/agents-and-tools/tool-use/web-fetch-tool  
  Focus: server-side content retrieval, PDF support, citations, dynamic filtering, security.

## Anthropic Announcements
- **Claude 3 family (reasoning, vision, long context, structured output)**  
  https://www.anthropic.com/news/claude-3-family

- **Claude 3.5 Sonnet (agentic coding, vision, Artifacts, Memory direction)**  
  https://www.anthropic.com/news/claude-3-5-sonnet

- **Claude Sonnet 4.6 (1M context, computer use improvements, extended thinking, compaction)**  
  https://www.anthropic.com/news/claude-sonnet-4-6

## Notes
- Sources above are the only basis for claims in `claude-skills-overview.md` and
  `claude-skills-top-20.md`. No non-Anthropic sources were used.
- Several features are labeled “beta” in the docs; these are treated as optional capabilities.


--- docs/claude/abstractframework-fit.md ---
# AbstractFramework Fit Analysis For Claude Skills (Feb 2026)

## Current AbstractFramework Capabilities (Relevant Snapshot)
Based on `README.md` and `docs/architecture.md`, the framework already provides:
- **Universal tool calling + MCP** via AbstractCore (single tool schema across providers).
- **Structured output** and **streaming/async** across providers.
- **Durable execution and auditability** via AbstractRuntime’s ledger and artifacts.
- **Memory system** via AbstractMemory + AbstractSemantics.
- **Chat compaction** in AbstractCore `BasicSession` for long conversations.
- **Multimodal input** with policy-driven fallbacks.

These align well with Claude’s API-first skills. The main gaps are provider-specific
capabilities that are not yet explicitly integrated (e.g., Anthropic server tools and
computer-use tool).

## Where Claude Skills Would Benefit AbstractFramework (Why + How)

### 1) Web Search Tool (Server Tool + Citations)
- **Why:** AbstractFramework already supports “deep search” use cases, but Claude’s server-side
  web search provides built-in citations and dynamic filtering for more reliable research results.
- **How:** Add an Anthropic-specific tool adapter in AbstractCore that registers `web_search`
  server tools. Store citations as artifacts linked in the ledger. Expose allowlist/denylist and
  `max_uses` in config. If disabled, emit `#FALLBACK` warnings and do not silently simulate search.
- **Evidence:** Claude web search tool docs show citations and dynamic filtering.

### 2) Web Fetch Tool (Pages + PDFs With Optional Citations)
- **Why:** AbstractFramework workflows often require document ingestion; web fetch adds a direct,
  cited path to pull full pages or PDFs with guardrails.
- **How:** Implement a server-tool mapping for `web_fetch` with strict domain controls, and
  enforce `max_content_tokens`. If truncation occurs, label `#TRUNCATION` in the ledger.
- **Evidence:** Claude web fetch docs describe PDF support, citations, and content limits.

### 3) Dynamic Filtering Via Code Execution (Server Tool Optimization)
- **Why:** Long document retrieval can be expensive. Claude’s dynamic filtering reduces token
  costs and improves relevance.
- **How:** When `web_search_20260209` or `web_fetch_20260209` is enabled, require a code-execution
  tool and sandbox it. Log filtering decisions and parameters in the ledger for auditability.
- **Evidence:** Web search/fetch docs note dynamic filtering and dependency on code execution.

### 4) Computer Use Tool (GUI Automation)
- **Why:** AbstractFramework already targets durable automation. Computer use enables tasks
  against legacy GUIs where APIs don’t exist.
- **How:** Add a computer-use tool integration as an optional capability with explicit user
  approval gates. Run in a sandboxed VM/container; store screenshots and action logs as artifacts.
  Enforce allowlisted domains and add prompt-injection warnings (`#FALLBACK` if disabled).
- **Evidence:** Computer use docs specify agent loops, action schemas, and safety constraints.

### 5) Thinking / Extended Thinking Controls
- **Why:** Many AbstractFramework flows (planning, code review, audits) benefit from controllable
  reasoning budgets to increase reliability.
- **How:** Extend AbstractCore provider settings to accept Anthropic `thinking` parameters and
  expose them in Flow node configs. Record the chosen budget in the ledger for reproducibility.
- **Evidence:** Computer use docs and Sonnet 4.6 announcement describe thinking modes.

### 6) Prompt Caching For Long-Running Workflows
- **Why:** Durable workflows often re-use large context; caching can reduce cost and latency.
- **How:** Add a session-level option to emit `cache_control` breakpoints in Anthropic requests.
  Record cache hit/miss metrics in the ledger when exposed by the API.
- **Evidence:** Web search/fetch docs describe cache_control usage for prompt caching.

### 7) Context Compaction Alignment
- **Why:** AbstractCore already has compaction; Claude’s platform compaction can further extend
  effective context. Coordinating the two avoids redundant summarization.
- **How:** Make Claude context compaction optional and mutually exclusive with BasicSession
  auto-compaction for a given run; emit `#FALLBACK` warnings if forced to downgrade.
- **Evidence:** Sonnet 4.6 announcement references context compaction.

### 8) Artifacts-Like Workspace In AbstractObserver / Code Web
- **Why:** Claude Artifacts demonstrate strong UX for code/document iteration. AbstractObserver
  and Code Web could surface ledger artifacts in a side pane to match this workflow.
- **How:** Add an “artifact workspace” UI surface for generated code/docs with inline editing,
  backed by ledger artifacts. Keep edits as new artifacts for full provenance.
- **Evidence:** Claude 3.5 Sonnet announcement describes Artifacts as a dedicated workspace.

### 9) Memory Tool Integration (Optional)
- **Why:** Claude Memory is positioned for preference retention; AbstractFramework already has
  a richer memory system. A thin integration could provide model-side personalization when desired.
- **How:** Map user preferences stored in AbstractMemory into Claude’s memory tool where available.
  Require explicit user consent and provide opt-in controls. Never silently sync.
- **Evidence:** Claude 3.5 Sonnet and Sonnet 4.6 announcements reference memory features.

### 10) Citation-Aware Outputs In Ledger And UIs
- **Why:** Claude server tools produce citations; surfacing them makes AbstractFramework’s
  auditability even stronger.
- **How:** Persist citations alongside tool results and render them in AbstractObserver. Ensure
  citations are preserved when outputs are post-processed.
- **Evidence:** Web search and web fetch docs describe citation structures.

## Skills That Are Already Covered (Low Incremental Value)
- **Text generation, reasoning, multilingual, vision, long context** are model capabilities
  already accessible via AbstractCore by selecting Claude models.
- **Tool calling, structured output, streaming** are already part of AbstractCore’s core
  abstraction; Claude can be plugged in without new architecture.
- **MCP integration** already exists in AbstractCore; Claude’s MCP support is complementary.

## Risks And Guardrails (Align With Framework Principles)
- **Prompt injection & unsafe automation:** Computer use and web tools require allowlists,
  human approval gates, and explicit warnings (`#FALLBACK` when safety constraints disable tools).
- **Truncation risk:** Web fetch and large content limits must tag `#TRUNCATION` and preserve
  provenance in the ledger.
- **Privacy:** Server tools are not always ZDR; the system should surface privacy mode in UI and logs.

## ADR Suggestion (Crucial Architecture Decision)
Create an ADR for “Anthropic Server Tools + Computer Use Integration” covering:
- Security model (allowlists, sandboxing, approvals)
- Logging and provenance requirements
- Fallback and truncation policy (`#FALLBACK`, `#TRUNCATION`)
- UX for citations and artifact outputs

