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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/notify-docs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Notify docs update

on:
push:
branches: [main]
paths:
- 'docs/**'

jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Trigger useforge.ai rebuild
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.USEFORGE_DISPATCH_TOKEN }}
repository: initializ/useforge.ai
event-type: docs-updated
client-payload: '{"ref": "${{ github.sha }}", "message": "${{ github.event.head_commit.message }}"}'
11 changes: 5 additions & 6 deletions docs/channels.md → docs/core-concepts/channels.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Channel Adapters

> Part of [Forge Documentation](../README.md)
---
title: "Channels"
description: "Bridge messaging platforms like Slack and Telegram to your AI agent."
order: 4
---

Channel adapters bridge messaging platforms (Slack, Telegram) to your A2A-compliant agent. Each adapter normalizes platform-specific events into a common `ChannelEvent` format, forwards them to the agent's A2A server, and delivers responses back to the originating platform.

Expand Down Expand Up @@ -227,6 +229,3 @@ type ChannelPlugin interface {
2. Implement `ChannelPlugin`.
3. Register the plugin in the channel registry.
4. Add config generation in `generateChannelConfig()` and env vars in `generateEnvVars()`.

---
← [Memory](memory.md) | [Back to README](../README.md) | [Security Overview](security/overview.md) →
11 changes: 5 additions & 6 deletions docs/hooks.md → docs/core-concepts/hooks.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Hooks

> Part of [Forge Documentation](../README.md)
---
title: "Hooks"
description: "Hook into the agent loop for logging, enforcement, and auditing."
order: 7
---

The hook system allows custom logic to run at key points in the LLM agent loop. Hooks can observe, modify context, or block execution.

Expand Down Expand Up @@ -142,6 +144,3 @@ exec := engine.NewLLMExecutor(engine.LLMExecutorConfig{
```

If no `HookRegistry` is provided, an empty one is created automatically.

---
← [Scheduling](scheduling.md) | [Back to README](../README.md) | [Commands](commands.md) →
11 changes: 5 additions & 6 deletions docs/architecture.md → docs/core-concepts/how-forge-works.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Architecture

> Part of [Forge Documentation](../README.md)
---
title: "How Forge Works"
description: "Understand Forge's architecture, module system, and data flows."
order: 1
---

Forge is a portable runtime for building and running secure AI agents from simple skill definitions.

Expand Down Expand Up @@ -359,6 +361,3 @@ The A2A server adds:
- **Request size limits** — `MaxHeaderBytes` (1 MiB) and `http.MaxBytesReader` (2 MiB) on request bodies; returns 413 on excess

See [Egress Security](security/egress.md) for details.

---
← [Installation](installation.md) | [Back to README](../README.md) | [Skills](skills.md) →
11 changes: 5 additions & 6 deletions docs/memory.md → docs/core-concepts/memory-system.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Memory

> Part of [Forge Documentation](../README.md)
---
title: "Memory System"
description: "Session persistence, context management, and long-term memory."
order: 5
---

Forge provides two layers of memory management: session persistence for multi-turn conversations and long-term memory for cross-session knowledge.

Expand Down Expand Up @@ -122,6 +124,3 @@ Environment variables:
| `FORGE_SESSION_MAX_AGE` | Session idle timeout, e.g. `30m`, `1h` (default: `30m`) |
| `FORGE_MEMORY_LONG_TERM` | Set `true` to enable long-term memory |
| `FORGE_EMBEDDING_PROVIDER` | Override embedding provider |

---
← [Runtime](runtime.md) | [Back to README](../README.md) | [Channels](channels.md) →
11 changes: 5 additions & 6 deletions docs/runtime.md → docs/core-concepts/runtime-engine.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# LLM Runtime Engine

> Part of [Forge Documentation](../README.md)
---
title: "Runtime Engine"
description: "The LLM runtime engine powering tool calling, memory, and hooks."
order: 6
---

The runtime engine powers `forge run` — executing agent tasks via LLM providers with tool calling, conversation memory, and lifecycle hooks.

Expand Down Expand Up @@ -254,6 +256,3 @@ The runner registers five hook groups: logging, audit, progress, global guardrai
## Streaming

The LLM tool-calling loop runs non-streaming internally. `ExecuteStream` calls `Execute` and emits the final response on a channel. However, the **UI chat proxy** (`forge-ui/chat.go`) streams A2A SSE events to the browser in real-time — `status` events carry incremental text, `progress` events carry tool execution updates, and `result` events carry the final response. The frontend renders text and tool progress as each event arrives.

---
← [Tools](tools.md) | [Back to README](../README.md) | [Memory](memory.md) →
11 changes: 5 additions & 6 deletions docs/scheduling.md → docs/core-concepts/scheduling.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Scheduling (Cron)

> Part of [Forge Documentation](../README.md)
---
title: "Scheduling"
description: "Built-in cron scheduler for recurring agent tasks."
order: 8
---

Forge includes a built-in cron scheduler for recurring tasks, configurable in `forge.yaml` or created dynamically by the agent at runtime.

Expand Down Expand Up @@ -53,6 +55,3 @@ When a schedule includes `channel` and `channel_target`, the agent's response is
- **Persistence**: Schedules are stored in `.forge/memory/SCHEDULES.md` and survive restarts
- **History**: The last 50 executions are recorded with status, duration, and correlation IDs
- **Audit events**: `schedule_fire`, `schedule_complete`, `schedule_skip`, `schedule_modify`

---
← [Guardrails](security/guardrails.md) | [Back to README](../README.md) | [Hooks](hooks.md) →
165 changes: 165 additions & 0 deletions docs/core-concepts/skill-md-format.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
---
title: "SKILL.md Format"
description: "Define agent skills using the SKILL.md format with YAML frontmatter and tool definitions."
order: 2
---

## SKILL.md Format

Skills are defined in Markdown files inside `skills/<skill-name>/SKILL.md`. Each file supports optional YAML frontmatter and two body formats.

```markdown
---
name: weather
icon: 🌤️
category: utilities
tags:
- weather
- forecast
- api
description: Weather data skill
metadata:
forge:
requires:
bins:
- curl
env:
required: []
one_of: []
optional: []
---
## Tool: weather_current

Get current weather for a location.

**Input:** location (string) - City name or coordinates
**Output:** Current temperature, conditions, humidity, and wind speed

## Tool: weather_forecast

Get weather forecast for a location.

**Input:** location (string), days (integer: 1-7)
**Output:** Daily forecast with high/low temperatures and conditions
```

Each `## Tool:` heading defines a tool the agent can call. The frontmatter declares binary dependencies and environment variable requirements. Skills compile into JSON artifacts and prompt text during `forge build`.

### YAML Frontmatter

Top-level fields:

| Field | Required | Description |
|-------|----------|-------------|
| `name` | yes | Skill identifier (kebab-case) |
| `icon` | yes | Emoji displayed in the TUI skill picker |
| `category` | yes | Grouping for `forge skills list --category` (e.g., `sre`, `developer`, `research`, `utilities`) |
| `tags` | yes | Discovery keywords for `forge skills list --tags` (kebab-case) |
| `description` | yes | One-line summary |

The `metadata.forge.requires` block declares runtime dependencies:

- **`bins`** — Binary dependencies that must be in `$PATH` at runtime
- **`env.required`** — Environment variables that must be set
- **`env.one_of`** — At least one of these environment variables must be set
- **`env.optional`** — Optional environment variables for extended functionality

Frontmatter is parsed by `ParseWithMetadata()` in `forge-skills/parser/parser.go` and feeds into the compilation pipeline.

### Legacy List Format

```markdown
# Agent Skills

- translate
- summarize
- classify
```

Single-word list items (no spaces, max 64 characters) create name-only skill entries. This format is simpler but provides less metadata.

## Skill Registry

Forge ships with a built-in skill registry. Add skills to your project with a single command:

```bash
# Add a skill from the registry
forge skills add tavily-research

# Validate skill requirements
forge skills validate

# Audit skill security
forge skills audit --embedded
```

`forge skills add` copies the skill's SKILL.md and any associated scripts into your project's `skills/` directory. It validates binary and environment requirements, checks for existing values in your environment, `.env` file, and encrypted secrets, and prompts only for truly missing values with a suggestion to use `forge secrets set` for sensitive keys. If the skill declares `egress_domains`, they are automatically merged into the `forge.yaml` `egress.allowed_domains` list (deduplicated and sorted).

## Skills as First-Class Tools

Script-backed skills are automatically registered as **first-class LLM tools** at runtime. When a skill has scripts in `skills/scripts/`, Forge:

1. Parses the skill's SKILL.md for tool definitions, descriptions, and input schemas
2. Creates a named tool for each `## Tool:` entry (e.g., `tavily_research` becomes a tool the LLM can call directly)
3. Executes the skill's shell script with JSON input when the LLM invokes it

This means the LLM sees skill tools alongside builtins like `web_search` and `http_request` — no generic `cli_execute` indirection needed.

For skills **without** scripts (binary-backed skills like `k8s-incident-triage`), Forge injects the full skill instructions into the system prompt. The complete SKILL.md body — including triage steps, detection heuristics, output structure, and safety constraints — is included inline so the LLM follows the skill protocol without needing an extra tool call. Skills are invoked via `cli_execute` with the declared binary dependencies.

```
┌─────────────────────────────────────────────────┐
│ LLM Tool Registry │
├─────────────────┬───────────────────────────────┤
│ Builtins │ web_search, http_request │
│ Skill Tools │ tavily_research, codegen_* │ ← auto-registered from scripts
│ read_skill │ load any SKILL.md on demand │
│ cli_execute │ run approved binaries │
├─────────────────┴───────────────────────────────┤
│ System Prompt: full skill instructions inline │ ← binary-backed skills
└─────────────────────────────────────────────────┘
```

## Skill Execution Security

Skill scripts run in a restricted environment via `SkillCommandExecutor`:

- **Isolated environment**: Only `PATH`, `HOME`, and explicitly declared env vars are passed through
- **OAuth token resolution**: When `OPENAI_API_KEY` is set to `__oauth__`, the executor resolves OAuth credentials and injects the access token, `OPENAI_BASE_URL`, and the configured model as `REVIEW_MODEL`
- **Configurable timeout**: Each skill declares a `timeout_hint` in its YAML frontmatter (e.g., 300s for research)
- **No shell execution**: Scripts run via `bash <script> <json-input>`, not through a shell interpreter
- **Egress proxy enforcement**: When egress mode is `allowlist` or `deny-all`, a local HTTP/HTTPS proxy is started and `HTTP_PROXY`/`HTTPS_PROXY` env vars are injected into subprocess environments, ensuring `curl`, `wget`, Python `requests`, and other HTTP clients route through the same domain allowlist used by in-process tools (see [Egress Security](security/egress.md))

### Symlink Escape Detection

The skill scanner validates symlinks when a filesystem root path is available. Symlinks that resolve outside the root directory are skipped with a warning log. This prevents malicious symlinks in skill directories from escaping the project boundary. The scanner exposes `ScanWithRoot(fsys, rootPath)` for callers that need symlink validation, while the original `Scan(fsys)` remains backward-compatible.

### Trust Policy Defaults

The default trust policy requires checksum verification (`RequireChecksum: true`). Skills loaded without a signature emit a warning log at scan time. Signature verification remains opt-in (`RequireSignature: false`).

## Skill Categories & Tags

All embedded skills must declare `category`, `tags`, and `icon` in their frontmatter. Categories and tags must be lowercase kebab-case.

```markdown
---
name: k8s-incident-triage
icon: ☸️
category: sre
tags:
- kubernetes
- incident-response
- triage
---
```

Use categories and tags to filter skills:

```bash
# List skills by category
forge skills list --category sre

# Filter by tags (AND semantics — skill must have all listed tags)
forge skills list --tags kubernetes,incident-response
```
11 changes: 5 additions & 6 deletions docs/tools.md → docs/core-concepts/tools-and-builtins.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Tools

> Part of [Forge Documentation](../README.md)
---
title: "Tools & Builtins"
description: "Built-in tools, adapter tools, and the pluggable tool system."
order: 3
---

Tools are capabilities that an LLM agent can invoke during execution. Forge provides a pluggable tool system with built-in tools, adapter tools, development tools, and custom tools.

Expand Down Expand Up @@ -248,6 +250,3 @@ The `ToolFilterStage` runs during `forge build`:
2. Sets `tool_interface_version` to `"1.0"` on the AgentSpec
3. In production mode (`--prod`), removes all dev-category tools
4. Counts tools per category for the build manifest

---
← [Skills](skills.md) | [Back to README](../README.md) | [Runtime](runtime.md) →
Loading
Loading