# Goose (Block) AI Agent — Architecture & Customization Research Report

> **Last Updated:** 2026-02-06  
> **Purpose:** Deep research for forking/cloning Goose into a custom agent  
> **License:** Apache 2.0 (permissive, allows derivative works & white-labeling)

---

## Table of Contents
1. [Repository Structure](#1-repository-structure)
2. [Core Architecture Deep Dive](#2-core-architecture-deep-dive)
3. [Desktop UI Architecture](#3-desktop-ui-architecture)
4. [MCP Integration System](#4-mcp-integration-system)
5. [Extension/Plugin System](#5-extensionplugin-system)
6. [Permission & HITL System](#6-permission--hitl-system)
7. [Forking Strategy](#7-forking-strategy)
8. [Community Extensions & Patterns](#8-community-extensions--patterns)
9. [Key Findings for Custom Agent Development](#9-key-findings-for-custom-agent-development)
10. [Sources](#10-sources)

---

## 1. Repository Structure

**Repo:** https://github.com/block/goose

Goose is a Rust + TypeScript monorepo with the following key structure:

```
block/goose/
├── crates/
│   ├── goose/              # Core agent logic (the brain)
│   │   └── src/
│   │       ├── agents/
│   │       │   ├── agent.rs        # Main agent implementation
│   │       │   └── extension.rs    # ExtensionConfig enum (L87-200)
│   │       └── providers/
│   │           └── base.rs         # Provider trait definition
│   ├── goose-bench/        # Benchmarking framework
│   ├── goose-cli/          # CLI entry point
│   │   └── src/
│   │       ├── main.rs             # CLI entry point
│   │       └── commands/
│   │           ├── configure.rs    # Provider/extension configuration
│   │           └── mcp.rs          # MCP server command handling
│   ├── goose-server/       # Backend HTTP server (binary: goosed)
│   │   └── src/main.rs            # Server entry point
│   ├── goose-mcp/          # Built-in MCP extensions (developer, memory, etc.)
│   │   └── src/
│   │       └── developer/
│   │           └── tools/
│   │               └── shell.rs    # Shell tool example
│   ├── goose-test/         # Test utilities
│   ├── mcp-client/         # MCP client implementation
│   ├── mcp-core/           # MCP shared types/primitives
│   └── mcp-server/         # MCP server framework
├── temporal-service/       # Go-based scheduler service
├── ui/desktop/             # Electron + React desktop app
│   ├── package.json        # Dependencies & build scripts
│   ├── src/
│   │   ├── main.ts                 # Electron main process
│   │   ├── App.tsx                 # React root component
│   │   ├── goosed.ts               # Backend connection manager
│   │   ├── built-in-extensions.json # Built-in extension registry
│   │   ├── components/             # React UI components
│   │   │   ├── BaseChat.tsx        # Base chat container
│   │   │   ├── ChatInput.tsx       # User input component (59KB!)
│   │   │   ├── ChatSessionsContainer.tsx
│   │   │   ├── ElicitationRequest.tsx  # MCP elicitation UI
│   │   │   ├── ConfigContext.tsx
│   │   │   ├── ExtensionInstallModal.test.tsx
│   │   │   └── ErrorBoundary.tsx
│   │   ├── api/                    # Generated OpenAPI client
│   │   ├── assets/                 # Static assets (branding)
│   │   ├── contexts/               # React contexts
│   │   ├── constants/
│   │   └── utils/
│   │       ├── logger.ts
│   │       ├── autoUpdater.ts
│   │       ├── settings.ts
│   │       └── urlSecurity.ts
│   └── openapi.json        # Auto-generated, DO NOT EDIT
├── AGENTS.md               # AI-agent dev instructions
├── HOWTOAI.md              # AI-assisted dev guide
├── GOVERNANCE.md           # Project governance
├── LICENSE                 # Apache 2.0
└── Justfile                # Task runner recipes
```

### Entry Points
| Entry Point | File | Purpose |
|---|---|---|
| CLI | `crates/goose-cli/src/main.rs` | Terminal interface |
| Server | `crates/goose-server/src/main.rs` | Backend daemon (`goosed`) |
| Desktop UI | `ui/desktop/src/main.ts` | Electron main process |
| Agent Core | `crates/goose/src/agents/agent.rs` | Core agent logic |

---

## 2. Core Architecture Deep Dive

### Execution Flow

The core flow is: **Message → Agent → Provider (LLM) → Tool execution → Response**

The agent operates in an **interactive loop**:

1. **Human Request** → User provides input via CLI or Desktop
2. **Provider Chat** → Agent sends request + available tools list to LLM provider
3. **Model Extension Call** → LLM returns tool call request (JSON); Goose executes it
4. **Response to Model** → Tool results sent back to LLM; loop repeats if more tools needed
5. **Context Revision** → Old/irrelevant info pruned (token management)
6. **Model Response** → Final text response back to user

### Session Management

- Sessions are persisted as **JSONL files** with automatic backup and recovery
- Session history includes conversation, tool execution results, and user preferences
- Sessions survive restarts via the `session/load` mechanism
- Config stored at `~/.config/goose/config.yaml` (macOS/Linux) or `%APPDATA%\Block\goose\config\config.yaml` (Windows)

### Provider Abstraction

Goose supports multiple LLM providers through a unified `Provider` trait:
- Defined in `crates/goose/src/providers/base.rs`
- Implementations handle auth, request formatting, response streaming
- Multi-model config: supports lead/worker mode, planner model, and tool shim model
- Key config variables: `GOOSE_PROVIDER`, `GOOSE_MODEL`, `GOOSE_TEMPERATURE`

### Backend Server (goosed)

The backend `goosed` runs as a separate process, currently using a custom REST + SSE streaming API:

- **Current:** Custom SSE-based streaming consumed by the Electron desktop app
- **Upcoming (ACP migration — Issue #6642):** Replacing with Agent Communication Protocol (ACP) over HTTP
  - JSON-RPC 2.0 transport
  - `POST /acp/session` — Create session
  - `POST /acp/session/{id}/message` — Send JSON-RPC request
  - `GET /acp/session/{id}/stream` — SSE stream for all server→client messages
  - Supports permission flow: server sends `request_permission`, client responds with `allow_once`/deny

### Error Handling

- Errors are captured and sent back to the model as tool responses
- Uses `anyhow::Result` throughout the Rust codebase
- Invalid JSON, missing tools, etc. → LLM gets error context to self-correct

---

## 3. Desktop UI Architecture

### Tech Stack

| Layer | Technology |
|---|---|
| Framework | **Electron** (v40.1.0) |
| Frontend | **React 19** + TypeScript |
| Build | **Vite** + **electron-forge** |
| Styling | **TailwindCSS 4** + Radix UI primitives |
| State | SWR for data fetching, React contexts |
| Markdown | react-markdown + remark-gfm + rehype-katex |
| Code Highlighting | react-syntax-highlighter |
| Icons | lucide-react + react-icons |
| API Client | Auto-generated from OpenAPI spec (`@hey-api/openapi-ts`) |
| Testing | Vitest + Playwright (E2E) + Testing Library |
| MCP UI | `@mcp-ui/client` (v5.17.3) |

### Key UI Components

| Component | File | Purpose |
|---|---|---|
| Base Chat | `BaseChat.tsx` (17.7KB) | Core chat container, message rendering |
| Chat Input | `ChatInput.tsx` (59KB) | User input with slash commands, file attachments |
| Chat Sessions | `ChatSessionsContainer.tsx` | Multi-session management |
| Elicitation | `ElicitationRequest.tsx` | MCP elicitation request UI |
| Extension Install | `ExtensionInstallModal.test.tsx` | Extension installation flow |
| Config | `ConfigContext.tsx` | App configuration context |
| Error Boundary | `ErrorBoundary.tsx` | Error handling wrapper |
| API Key Tester | `ApiKeyTester.tsx` | Provider key validation |

### Frontend-Backend Communication

1. Electron main process (`main.ts`) spawns `goosed` backend
2. React frontend communicates via generated OpenAPI client
3. Real-time streaming via SSE connections
4. IPC bridge for Electron-specific features (file dialogs, system tray, etc.)

### Deep Link Protocol

Goose supports `goose://` protocol URLs for:
- `goose://extension?cmd=...` — Install extensions
- `goose://bot` or `goose://recipe` — Launch recipes
- `goose://sessions` — Open shared sessions

### Branding Files

Key branding touchpoints for white-labeling:
- `ui/desktop/package.json` — `productName: "Goose"`, `name: "goose-app"`
- `ui/desktop/src/assets/` — Logo, icons, images
- `ui/desktop/src/main.ts` — Window title, tray icon, protocol handler (`goose://`)
- `ui/desktop/src/built-in-extensions.json` — Default extension list

---

## 4. MCP Integration System

### Architecture

Goose acts as an **MCP Host** managing multiple MCP clients, each connected to a server (extension):

```
┌─────────────────────────────────────┐
│ Goose Host Process                  │
│ ┌────────────────────────────────┐  │
│ │ Goose Application (Host)       │  │
│ │                                │  │
│ │ ┌──────────┐  ┌──────────┐    │  │
│ │ │ Client 1 │  │ Client 2 │    │  │
│ │ └────┬─────┘  └────┬─────┘    │  │
│ └──────┼──────────────┼──────────┘  │
└────────┼──────────────┼─────────────┘
         │              │
         ▼              ▼
  ┌──────────┐   ┌──────────┐
  │ Server 1 │   │ Server 2 │
  │(Developer)│  │(Memory)  │
  └──────────┘   └──────────┘
```

### How Goose Discovers & Connects to MCP Servers

1. **Built-in extensions** are compiled into the `goosed` binary (defined in `crates/goose-mcp/`)
2. **Config-based extensions** are defined in `~/.config/goose/config.yaml`
3. **Deep links** install via `goose://extension?cmd=...`
4. **Extension Manager** (built-in platform extension) can dynamically discover, enable, and disable extensions during a session
5. **Smart Extension Recommendation** analyzes user tasks and suggests relevant extensions automatically

### Transport Mechanisms

| Type | Config Key | Use Case |
|---|---|---|
| **STDIO** | `type: stdio` | Local extensions (process-based, stdin/stdout) |
| **SSE** | `type: sse` | Remote HTTP-based extensions |
| **Streamable HTTP** | `type: streamablehttp` | Modern remote transport |

### Extension Config Format (config.yaml)

```yaml
extensions:
  github:
    name: GitHub
    cmd: npx
    args: [-y, @modelcontextprotocol/server-github]
    enabled: true
    envs: { "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>" }
    type: stdio
    timeout: 300
```

### MCP UI Rendering (Issue #3562 — Active Development)

Goose is building support for **rendering rich UI from MCP tool responses**:

- **Inline display**: Embedded in chat flow (data viz, previews)
- **Sidecar display**: Side panel for rich interaction (app-like experiences)
- Uses `@mcp-ui/client` library for deterministic rendering
- Tool responses include `_meta.goose.toolUI` metadata specifying display type and renderer
- Example MCP tool returning UI:

```typescript
server.tool('render_ui_inline', 'Display UI', {}, async () => {
  return {
    _meta: {
      goose: {
        toolUI: {
          displayType: 'inline',
          name: 'inline example',
          renderer: 'mcp-ui',
        },
      },
    },
    content: [
      createUIResource({
        uri: 'ui://component-html',
        content: { type: 'rawHtml', htmlString: '<p>Hello World</p>' },
        encoding: 'text',
      }),
    ],
  };
});
```

---

## 5. Extension/Plugin System

### Extension Trait (Rust)

```rust
#[async_trait]
pub trait Extension: Send + Sync {
    fn name(&self) -> &str;
    fn description(&self) -> &str;
    fn instructions(&self) -> &str;
    fn tools(&self) -> &[Tool];
    async fn status(&self) -> AnyhowResult<HashMap<String, Value>>;
    async fn call_tool(&self, tool_name: &str, parameters: HashMap<String, Value>) -> ToolResult<Value>;
}
```

### Built-in Extensions

Defined in `ui/desktop/src/built-in-extensions.json`:

| ID | Name | Default Enabled | Description |
|---|---|---|---|
| `developer` | Developer | ✅ | Shell, file editing, project tools |
| `computercontroller` | Computer Controller | ❌ | Webscraping, file caching, automations |
| `memory` | Memory | ❌ | Learn and recall user preferences |
| `autovisualiser` | Auto Visualiser | ❌ | Auto-generate data visualizations |
| `tutorial` | Tutorial | ❌ | Interactive learning guides |

### Platform Extensions (Always Available)

| Extension | Purpose |
|---|---|
| Chat Recall | Search across all session history |
| Code Execution | Execute JavaScript for tool discovery |
| Extension Manager | Dynamic extension discovery/management (enabled by default) |
| Skills | Load agent skills from project/global directories (enabled by default) |
| Todo | Task tracking across sessions (enabled by default) |

### Building Custom Extensions

Extensions are MCP servers. The recommended pattern:

1. Create an MCP server (Python with `FastMCP`, TypeScript with `@modelcontextprotocol/sdk`, or Rust)
2. Define tools with `@mcp.tool()` decorator (Python) or equivalent
3. Test with MCP Inspector (`mcp dev server.py`)
4. Register in Goose via Desktop UI, CLI, config file, or deep link

### Extension Allowlist (Enterprise)

For corporate environments, administrators can restrict which extensions can be installed:

```yaml
# Deployed YAML file at GOOSE_ALLOWLIST URL
extensions:
  - id: slack
    command: uvx mcp_slack
  - id: github
    command: uvx mcp_github
```

Set via `export GOOSE_ALLOWLIST=https://example.com/goose-allowlist.yaml`

---

## 6. Permission & HITL System

### Permission Modes

| Mode | Config Value | Behavior |
|---|---|---|
| **Autonomous** | `auto` | Full autonomy, no approval needed (**default**) |
| **Manual Approval** | `approve` | Confirmation before any tool use |
| **Smart Approval** | `smart_approve` | Risk-based: auto-approve low-risk, flag high-risk |
| **Chat Only** | `chat` | No tool use, conversation only |

Configuration: `GOOSE_MODE: smart_approve` in `config.yaml`

### How Approval Works

In `approve` and `smart_approve` modes:
1. Goose classifies tools as read or write (best-effort, LLM-interpreted)
2. Write tools trigger "Allow" / "Deny" buttons in the UI
3. The server sends a `request_permission` JSON-RPC request
4. Client responds with `{ outcome: "allow_once" }` or deny
5. Only after approval does the tool execute

### Additional Safety

- `.gooseignore` file prevents access to sensitive files (`.env*`, `*.key`, `target/`, `.git/`)
- `.goosehints` provides project-specific guidance to the agent
- Prompt injection detection (`SECURITY_PROMPT_ENABLED: true`)
- ML-based classifier endpoint for advanced threat detection
- Malware scanning for external extensions before activation
- Maximum turns limit (`GOOSE_MAX_TURNS`) prevents runaway loops

---

## 7. Forking Strategy

### License: Apache 2.0

✅ **Permissive license** — allows:
- Commercial use
- Modification and derivative works
- Distribution under different terms
- White-labeling and rebranding
- No copyleft/share-alike requirements

**Requirements:** Must include original copyright notice and license text.

**Note:** As of Dec 2025, Goose was contributed to the **Agentic AI Foundation (AAIF)** under the Linux Foundation. The Apache 2.0 license remains; governance is now community-driven.

### Key Files to Modify for White-Labeling

| What to Change | Files |
|---|---|
| **App Name & Branding** | `ui/desktop/package.json` (productName, name, description) |
| **Window Title** | `ui/desktop/src/main.ts` (BrowserWindow title) |
| **Protocol Handler** | `ui/desktop/src/main.ts` (`goose://` → `yourapp://`) |
| **Logo & Icons** | `ui/desktop/src/assets/` |
| **Built-in Extensions** | `ui/desktop/src/built-in-extensions.json` |
| **Default Config** | `crates/goose-server/` + `crates/goose-cli/` default values |
| **Config Directory** | Code references to `~/.config/goose/` |
| **System Prompts** | `crates/goose/src/agents/` — agent instructions |
| **Provider Defaults** | `GOOSE_PROVIDER`, `GOOSE_MODEL` defaults |
| **Update Server** | `ui/desktop/src/utils/autoUpdater.ts` |
| **Telemetry** | `GOOSE_TELEMETRY_ENABLED` and endpoints |
| **Extension Directory** | URL in extension browsing/discovery code |

### Adding Custom MCP Servers as Built-in Extensions

Two approaches:

1. **Rust built-in** (compiled into binary):
   - Add to `crates/goose-mcp/src/`
   - Register in the built-in server matching logic (`crates/goose-cli/src/commands/mcp.rs`)
   - Update `ui/desktop/src/built-in-extensions.json`
   
2. **Bundled external** (shipped alongside but run as separate process):
   - Include the MCP server binary/package in the distribution
   - Pre-configure in default `config.yaml`
   - Set `bundled: true` in extension config

### Build Process

```bash
# Setup
source bin/activate-hermit
cargo build

# Build release
cargo build --release
just release-binary

# Desktop app
just generate-openapi   # After server changes
just run-ui             # Development
cd ui/desktop && npm run bundle:default  # Production build
```

---

## 8. Community Extensions & Patterns

### Extension Discovery

- **Official directory:** https://block.github.io/goose/extensions/ (web-based catalog)
- **Community lists:** `appcypher/awesome-mcp-servers`, `punkpeye/awesome-mcp-servers`
- **Registries:** PulseMCP, Playbooks, MCP.so
- **Dynamic discovery:** Extension Manager extension searches available servers at runtime

### Common Extension Patterns

1. **STDIO MCP servers** (most common): `uvx`, `npx`, `jbang`, `docker` launchers
2. **Python + FastMCP**: Simplest pattern for custom tools
3. **TypeScript + @modelcontextprotocol/sdk**: For Node.js ecosystem
4. **Rust**: For performance-critical or compiled extensions

### Notable Community Extensions

| Extension | Command | Purpose |
|---|---|---|
| GitHub | `npx -y @modelcontextprotocol/server-github` | GitHub API integration |
| Slack | `uvx mcp_slack` | Slack workspace access |
| Postgres | `uvx mcp-server-postgres` | Database querying |
| Fetch | `uvx mcp-server-fetch` | HTTP request making |
| Filesystem | `uv run mcp-filesystem` | File system access |
| Playwright | MCP server | Browser automation |
| Tavily Search | `npx -y mcp-tavily-search` | Web search |
| Perplexity | `npx -y mcp-perplexity-search` | AI search |

### Recipes System

Goose supports **recipes** — shareable YAML files that package entire workflows:
- Include goal, required extensions, setup steps, example activities
- Configurable via `GOOSE_RECIPE_GITHUB_REPO`
- Custom slash commands can trigger recipes
- Deep linkable: `goose://recipe?...`

### Subagents

Goose supports spawning **subagents** — isolated instances for parallel/long-running tasks:
- Keep main conversation clean
- Process isolation for experimental work
- Parallel execution of independent tasks

---

## 9. Key Findings for Custom Agent Development

### Why Fork Goose?

| Advantage | Detail |
|---|---|
| **Mature MCP integration** | Best-in-class MCP host with dynamic discovery |
| **Desktop + CLI** | Two interfaces already built |
| **Apache 2.0** | Full commercial freedom |
| **Active development** | Frequent releases, large community |
| **Multi-provider** | Works with any LLM (OpenAI, Anthropic, Google, local) |
| **Permission system** | Built-in HITL with smart approval |
| **Extension ecosystem** | Thousands of MCP servers available |

### Customization Effort Estimate

| Change | Effort | Complexity |
|---|---|---|
| Rebrand (name, logo, colors) | 1-2 days | Low |
| Custom default extensions | 1 day | Low |
| Custom system prompts | Hours | Low |
| New built-in MCP extension (Rust) | 3-5 days | Medium |
| Custom UI components in chat | 1-2 weeks | Medium-High |
| Custom approval flow | 1 week | Medium |
| Replace backend protocol (ACP) | Already in progress upstream | High |

### Desktop App is More Extensible

The Electron desktop app provides:
- Full React component library for custom UI
- Deep link protocol for integrations
- Extension install modal workflow
- MCP UI rendering (inline + sidecar) — under active development
- System tray, keyboard shortcuts, auto-updates
- Multi-window/multi-session support

The CLI is simpler but less extensible for custom UI experiences.

### Risks & Considerations

1. **Active ACP migration** (Issue #6642): The backend communication protocol is being replaced. Fork timing matters.
2. **Governance shift**: Now under AAIF/Linux Foundation — community governance may affect upstream direction
3. **Rapid iteration**: Multiple releases per week; staying in sync with upstream requires effort
4. **Electron size**: Desktop app ships Chromium (~200MB+)
5. **Rust build times**: Full build can be slow; incremental builds are faster

---

## 10. Sources

| Source | URL |
|---|---|
| GitHub Repository | https://github.com/block/goose |
| Official Documentation | https://block.github.io/goose/ |
| AGENTS.md (repo structure) | https://raw.githubusercontent.com/block/goose/main/AGENTS.md |
| HOWTOAI.md (architecture) | https://raw.githubusercontent.com/block/goose/main/HOWTOAI.md |
| GOVERNANCE.md | https://raw.githubusercontent.com/block/goose/main/GOVERNANCE.md |
| Architecture Overview | https://block.github.io/goose/docs/goose-architecture/ |
| Extensions Design | https://block.github.io/goose/docs/goose-architecture/extensions-design/ |
| Config Files Guide | https://block.github.io/goose/docs/guides/config-files/ |
| Permission Modes | https://block.github.io/goose/docs/guides/goose-permissions/ |
| Using Extensions | https://block.github.io/goose/docs/getting-started/using-extensions/ |
| Extension Allowlist | https://block.github.io/goose/docs/guides/allowlist/ |
| MCP UI Issue #3562 | https://github.com/block/goose/issues/3562 |
| ACP Migration Issue #6642 | https://github.com/block/goose/issues/6642 |
| Block Announcement | https://block.xyz/inside/block-open-source-introduces-codename-goose |
| AAIF Launch | https://www.linuxfoundation.org/press/linux-foundation-announces-the-formation-of-the-agentic-ai-foundation |
| Extension Deep Dive (dev.to) | https://dev.to/lymah/deep-dive-into-gooses-extension-system-and-model-context-protocol-mcp-3ehl |
| Dynamic MCP Discovery | https://dev.to/amandamartindev/dynamic-mcp-server-discovery-with-goose-3m41 |
| What is Block Goose | https://jeffbailey.us/blog/2025/07/29/what-is-block-goose/ |
| Docker + Goose | https://www.docker.com/blog/building-ai-agents-with-goose-and-docker/ |
| Extensions Directory | https://block.github.io/goose/extensions/ |
| Desktop package.json | https://raw.githubusercontent.com/block/goose/main/ui/desktop/package.json |
| Built-in Extensions JSON | https://raw.githubusercontent.com/block/goose/main/ui/desktop/src/built-in-extensions.json |
| DeepWiki Overview | https://deepwiki.com/block/goose |
