Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
ee5a08e
feat: introduce tool catalog for built-in tool management
langowarny Mar 1, 2026
5792b5a
Merge branch 'feature/builtin-tool-catalog' into dev
langowarny Mar 1, 2026
d368b33
fix: improve agent error resilience for Gemini turn-order and max turns
langowarny Mar 1, 2026
f68c268
feat: openspec specs updated
langowarny Mar 1, 2026
b977eaa
Merge pull request #37 from langoai/claude/fervent-chebyshev
langowarny Mar 1, 2026
c554709
fix: enhance Docker permissions and directory setup
langowarny Mar 2, 2026
89b79d0
Merge pull request #38 from langoai/claude/peaceful-faraday
langowarny Mar 2, 2026
097db15
feat: enhance context error handling and improve typing indicator safety
langowarny Mar 2, 2026
3a7f63a
Merge pull request #39 from langoai/claude/suspicious-visvesvaraya
langowarny Mar 2, 2026
6444eca
feat: preserve Thought and ThoughtSignature in ToolCall across data flow
langowarny Mar 2, 2026
e2de0d5
feat: implement sub-agent auto-escalation and enhance rejection handling
langowarny Mar 2, 2026
c88e026
Merge pull request #40 from langoai/feature/tool-call-thought-enhance…
langowarny Mar 2, 2026
e1df889
feat: enhance onboarding forms with reactive model fetching
langowarny Mar 2, 2026
e948a37
feat: add Event Bus package for decoupling event handling
langowarny Mar 2, 2026
7973d75
chore: update project descriptions and enhance README layout
langowarny Mar 2, 2026
0446212
feat: integrate P2P settlement service and enhance payment processing
langowarny Mar 3, 2026
e595148
feat: add buyer-side automatic payment tool for P2P interactions
langowarny Mar 3, 2026
b88d2b7
Merge pull request #41 from langoai/feature/ap2-x402
langowarny Mar 3, 2026
4e066d3
feat: add advanced multi-agent orchestration with dynamic registry, h…
langowarny Mar 3, 2026
cf647f9
Merge pull request #42 from langoai/feature/advanced-multi-agent-orch…
langowarny Mar 3, 2026
9f1125f
docs: sync documentation with v0.3.0+ features
langowarny Mar 3, 2026
623a9e2
refactor: streamline code for efficiency and maintainability
langowarny Mar 4, 2026
3a07fad
Merge pull request #43 from langoai/feature/code-review-cleanup
langowarny Mar 4, 2026
9f00565
feat: add CLI/TUI subcommands, doctor checks, and documentation
langowarny Mar 4, 2026
a9c0b3e
Merge pull request #44 from langoai/feature/cli-tui-docs-update
langowarny Mar 4, 2026
2e39dae
refactor: golangci link fix
langowarny Mar 4, 2026
caa1897
feat: integrate MCP server support and configuration
langowarny Mar 5, 2026
9be8421
feat: add MCP form and configuration options to CLI
langowarny Mar 5, 2026
1cc4c8c
feat: enhance MCP integration with CLI commands and documentation
langowarny Mar 5, 2026
2a3769e
feat: add MCP server management to CLI settings
langowarny Mar 5, 2026
f6eaa92
Merge pull request #45 from langoai/feature/plugins
langowarny Mar 5, 2026
fdabcd5
fix: go lint fix
langowarny Mar 5, 2026
22a8c06
feat: update README.md to reflect new Lango features and economic model
langowarny Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
15 changes: 14 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,26 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*

RUN groupadd -r lango && useradd -r -g lango -m -d /home/lango lango \
&& mkdir -p /home/lango/.lango && chown lango:lango /home/lango/.lango
&& mkdir -p /home/lango/.lango/skills \
&& mkdir -p /home/lango/bin \
&& chown -R lango:lango /home/lango/.lango /home/lango/bin

COPY --from=builder /app/lango /usr/local/bin/lango
COPY --from=builder /app/prompts/ /usr/share/lango/prompts/
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

# Optional: install Go toolchain for agents that need `go install` capability.
# Build with --build-arg INSTALL_GO=true to enable.
ARG INSTALL_GO=false
RUN if [ "$INSTALL_GO" = "true" ]; then \
curl -fsSL https://go.dev/dl/go1.25.linux-amd64.tar.gz \
| tar -C /usr/local -xzf - ; \
fi

ENV PATH="/home/lango/bin:/home/lango/go/bin:/usr/local/go/bin:${PATH}"
ENV GOPATH="/home/lango/go"

USER lango
WORKDIR /home/lango

Expand Down
110 changes: 106 additions & 4 deletions README.md

Large diffs are not rendered by default.

72 changes: 72 additions & 0 deletions cmd/lango/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ import (
"github.com/langoai/lango/internal/app"
"github.com/langoai/lango/internal/background"
"github.com/langoai/lango/internal/bootstrap"
clia2a "github.com/langoai/lango/internal/cli/a2a"
cliagent "github.com/langoai/lango/internal/cli/agent"
cliapproval "github.com/langoai/lango/internal/cli/approval"
clibg "github.com/langoai/lango/internal/cli/bg"
clicron "github.com/langoai/lango/internal/cli/cron"
climcp "github.com/langoai/lango/internal/cli/mcp"
"github.com/langoai/lango/internal/cli/doctor"
cligraph "github.com/langoai/lango/internal/cli/graph"
clilearning "github.com/langoai/lango/internal/cli/learning"
clilibrarian "github.com/langoai/lango/internal/cli/librarian"
climemory "github.com/langoai/lango/internal/cli/memory"
"github.com/langoai/lango/internal/cli/onboard"
clip2p "github.com/langoai/lango/internal/cli/p2p"
Expand Down Expand Up @@ -123,6 +128,58 @@ func main() {
graphCmd.GroupID = "data"
rootCmd.AddCommand(graphCmd)

a2aCmd := clia2a.NewA2ACmd(func() (*config.Config, error) {
boot, err := bootstrap.Run(bootstrap.Options{})
if err != nil {
return nil, err
}
defer boot.DBClient.Close()
return boot.Config, nil
})
a2aCmd.GroupID = "data"
rootCmd.AddCommand(a2aCmd)

learningCfgLoader := func() (*config.Config, error) {
boot, err := bootstrap.Run(bootstrap.Options{})
if err != nil {
return nil, err
}
defer boot.DBClient.Close()
return boot.Config, nil
}
learningBootLoader := func() (*bootstrap.Result, error) {
return bootstrap.Run(bootstrap.Options{})
}
learningCmd := clilearning.NewLearningCmd(learningCfgLoader, learningBootLoader)
learningCmd.GroupID = "data"
rootCmd.AddCommand(learningCmd)

librarianCfgLoader := func() (*config.Config, error) {
boot, err := bootstrap.Run(bootstrap.Options{})
if err != nil {
return nil, err
}
defer boot.DBClient.Close()
return boot.Config, nil
}
librarianBootLoader := func() (*bootstrap.Result, error) {
return bootstrap.Run(bootstrap.Options{})
}
librarianCmd := clilibrarian.NewLibrarianCmd(librarianCfgLoader, librarianBootLoader)
librarianCmd.GroupID = "data"
rootCmd.AddCommand(librarianCmd)

approvalCmd := cliapproval.NewApprovalCmd(func() (*config.Config, error) {
boot, err := bootstrap.Run(bootstrap.Options{})
if err != nil {
return nil, err
}
defer boot.DBClient.Close()
return boot.Config, nil
})
approvalCmd.GroupID = "infra"
rootCmd.AddCommand(approvalCmd)

paymentCmd := clipayment.NewPaymentCmd(func() (*bootstrap.Result, error) {
return bootstrap.Run(bootstrap.Options{})
})
Expand All @@ -135,6 +192,21 @@ func main() {
p2pCmd.GroupID = "infra"
rootCmd.AddCommand(p2pCmd)

mcpCfgLoader := func() (*config.Config, error) {
boot, err := bootstrap.Run(bootstrap.Options{})
if err != nil {
return nil, err
}
defer boot.DBClient.Close()
return boot.Config, nil
}
mcpBootLoader := func() (*bootstrap.Result, error) {
return bootstrap.Run(bootstrap.Options{})
}
mcpCmd := climcp.NewMCPCmd(mcpCfgLoader, mcpBootLoader)
mcpCmd.GroupID = "infra"
rootCmd.AddCommand(mcpCmd)

cronCmd := clicron.NewCronCmd(func() (*bootstrap.Result, error) {
return bootstrap.Run(bootstrap.Options{})
})
Expand Down
5 changes: 5 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@ services:
restart: unless-stopped
ports:
- "18789:18789"
# - "9000:9000" # P2P libp2p (uncomment to enable P2P networking)
volumes:
- lango-data:/home/lango/.lango
secrets:
- lango_config
- lango_passphrase
environment:
- LANGO_PROFILE=default
# - LANGO_MULTI_AGENT=true # Enable multi-agent orchestration
# - LANGO_P2P=true # Enable P2P networking
# - LANGO_AGENT_MEMORY=true # Enable per-agent persistent memory
# - LANGO_HOOKS=true # Enable tool execution hooks

presidio-analyzer:
image: mcr.microsoft.com/presidio-analyzer:latest
Expand Down
12 changes: 11 additions & 1 deletion docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@
set -e

LANGO_DIR="$HOME/.lango"
mkdir -p "$LANGO_DIR"
mkdir -p "$LANGO_DIR/skills" "$HOME/bin"

# Verify write permissions on critical directories.
# Named Docker volumes can inherit stale ownership from previous builds.
for dir in "$LANGO_DIR" "$LANGO_DIR/skills" "$HOME/bin"; do
if [ -d "$dir" ] && ! [ -w "$dir" ]; then
echo "ERROR: $dir is not writable by $(whoami) (uid=$(id -u))." >&2
echo " Hint: remove the volume and recreate it: docker volume rm lango-data" >&2
exit 1
fi
done

# Set up passphrase keyfile from Docker secret.
# The keyfile path (~/.lango/keyfile) is blocked by the agent's filesystem tool.
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Architecture

This section describes the internal architecture of Lango, a Go-based AI agent framework built on Google ADK v0.4.0.
This section describes the internal architecture of Lango, a Go-based AI agent built on Google ADK v0.4.0.

<div class="grid cards" markdown>

Expand Down
17 changes: 15 additions & 2 deletions docs/architecture/project-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@ All application code lives under `internal/` to enforce Go's visibility boundary

| Package | Description |
|---------|-------------|
| `adk/` | Google ADK v0.4.0 integration. Contains `Agent` (wraps ADK runner), `ModelAdapter` (bridges `provider.ProviderProxy` to ADK `model.LLM`), `ContextAwareModelAdapter` (injects knowledge/memory/RAG into system prompt), `SessionServiceAdapter` (bridges internal session store to ADK session interface), and `AdaptTool()` (converts `agent.Tool` to ADK `tool.Tool`) |
| `adk/` | Google ADK v0.5.0 integration. Contains `Agent` (wraps ADK runner), `ModelAdapter` (bridges `provider.ProviderProxy` to ADK `model.LLM`), `ContextAwareModelAdapter` (injects knowledge/memory/RAG into system prompt), `SessionServiceAdapter` (bridges internal session store to ADK session interface), `ChildSessionServiceAdapter` (fork/merge child sessions for sub-agent isolation), `Summarizer` (extracts key results from child sessions), and `AdaptTool()` (converts `agent.Tool` to ADK `tool.Tool`) |
| `agent/` | Core agent types: `Tool` struct (name, description, parameters, handler), `ParameterDef`, `PII Redactor` (regex + optional Presidio integration), `SecretScanner` (prevents credential leakage in model output) |
| `app/` | Application bootstrap and wiring. `app.go` defines `New()` (component initialization), `Start()`, and `Stop()`. `wiring.go` contains all `init*` functions that create individual subsystems. `types.go` defines the `App` struct with all component fields. `tools.go` builds tool collections. `sender.go` provides `channelSender` adapter for delivery |
| `bootstrap/` | Pre-application startup: opens database, initializes crypto provider, loads config profile. Returns `bootstrap.Result` with shared `DBClient` and `Crypto` provider for reuse |
| `agentregistry/` | Agent definition registry. `Registry` loads built-in agents and user-defined `AGENT.md` files from `agent.agentsDir`. Provides `Specs()` for orchestrator routing and `Active()` for runtime agent listing |
| `agentmemory/` | Per-agent persistent memory. `Store` interface with `Save()`, `Get()`, `Search()`, `Delete()`, `Prune()` operations. Scoped by agent name for cross-session context retention |
| `ctxkeys/` | Context key helpers. `WithAgentName()` / `AgentNameFromContext()` for propagating agent identity through request contexts |
| `eventbus/` | Typed synchronous event pub/sub. `Bus` with `Subscribe()` / `Publish()`. `SubscribeTyped[T]()` generic helper for type-safe subscriptions. Events: ContentSaved, TriplesExtracted, TurnCompleted, ReputationChanged |
| `types/` | Shared type definitions used across packages: `ProviderType`, `Role`, `RPCSenderFunc`, `ChannelType`, `ConfidenceLevel`, `TokenUsage` |

### Presentation

Expand All @@ -51,6 +56,7 @@ All application code lives under `internal/` to enforce Go's visibility boundary
| `cli/workflow/` | `lango workflow run`, `list`, `status`, `cancel`, `history` -- workflow management |
| `cli/prompt/` | Interactive prompt utilities for CLI input |
| `cli/security/` | `lango security status`, `secrets`, `migrate-passphrase`, `keyring store/clear/status`, `db-migrate`, `db-decrypt`, `kms status/test/keys` -- security operations |
| `cli/tuicore/` | Shared TUI components for interactive terminal sessions. `FormModel` (Bubbletea form manager), `Field` struct with input types: `InputText`, `InputInt`, `InputPassword`, `InputBool`, `InputSelect`, `InputSearchSelect` |
| `cli/p2p/` | `lango p2p status`, `peers`, `connect`, `disconnect`, `firewall list/add/remove`, `discover`, `identity`, `reputation`, `pricing`, `session list/revoke/revoke-all`, `sandbox status/test/cleanup` -- P2P network management |
| `cli/tui/` | TUI components and views for interactive terminal sessions |
| `channels/` | Channel bot integrations for Telegram, Discord, and Slack. Each adapter converts platform-specific messages to the Gateway's internal format |
Expand Down Expand Up @@ -95,8 +101,12 @@ All application code lives under `internal/` to enforce Go's visibility boundary
| `keyring/` | Hardware keyring integration (Touch ID / TPM 2.0). `Provider` interface backed by OS keyring via go-keyring |
| `sandbox/` | Tool execution isolation. `SubprocessExecutor` for process-isolated P2P tool execution. `ContainerRuntime` interface with Docker/gVisor/native fallback chain. Optional pre-warmed container pool |
| `dbmigrate/` | Database encryption migration. `MigrateToEncrypted` / `DecryptToPlaintext` for SQLCipher transitions. `IsEncrypted` detection and `secureDeleteFile` cleanup |
| `toolcatalog/` | Thread-safe tool registry with category grouping. `Catalog` with `Register()`, `Get()`, `ListCategories()`, `ListTools()`. `ToolEntry` pairs tools with categories, `ToolSchema` provides tool summaries |
| `toolchain/` | HTTP-style middleware chain for tool wrapping. `Middleware` type, `Chain()` / `ChainAll()` functions. Built-in middlewares: security filter, access control, event publishing, knowledge save, approval, browser recovery |
| `appinit/` | Declarative module initialization system. `Module` interface with `Provides` / `DependsOn` keys. `Builder` with Kahn's algorithm topological sort for dependency resolution. Foundation for ordered application bootstrap |
| `asyncbuf/` | Generic async batch processor. `BatchBuffer[T]` with configurable batch size, flush interval, and backpressure. `Start()` / `Enqueue()` / `Stop()` lifecycle. Replaces per-subsystem buffer implementations |
| `passphrase/` | Passphrase prompt and validation helpers for terminal input |
| `orchestration/` | Multi-agent orchestration. `BuildAgentTree()` creates an ADK agent hierarchy with sub-agents: Operator (tool execution), Navigator (research), Vault (security), Librarian (knowledge), Automator (cron/bg/workflow), Planner (task planning), Chronicler (memory) |
| `orchestration/` | Multi-agent orchestration. `BuildAgentTree()` creates an ADK agent hierarchy. `AgentSpec` defines agent metadata (prefixes, keywords, capabilities). `PartitionToolsDynamic()` allocates tools to agents via multi-signal matching (prefix, keyword, capability). `BuiltinSpecs()` returns default agent definitions. Sub-agents: Operator, Navigator, Vault, Librarian, Automator, Planner, Chronicler. Supports user-defined agents via `AgentRegistry` |
| `a2a/` | Agent-to-Agent protocol. `Server` exposes agent card and task endpoints. `LoadRemoteAgents()` discovers and loads remote agent capabilities |
| `tools/` | Built-in tool implementations |
| `tools/browser/` | Headless browser tool with session management |
Expand All @@ -105,6 +115,9 @@ All application code lives under `internal/` to enforce Go's visibility boundary
| `tools/filesystem/` | File read/write/list tools with path allowlisting and blocklisting |
| `tools/secrets/` | Secret management tools (store, retrieve, list, delete) |
| `tools/payment/` | Payment tools (balance, send, history) |
| `p2p/team/` | P2P team coordination. `Team` manages task-scoped agent groups with roles (Leader, Worker, Reviewer, Observer). `ScopedContext` controls metadata sharing. Budget tracking via `AddSpend()`. Team lifecycle: Forming → Active → Completed/Disbanded |
| `p2p/agentpool/` | P2P agent pool with health monitoring. `Pool` manages discovered agents. `HealthChecker` runs periodic probes (Healthy/Degraded/Unhealthy/Unknown). `Selector` provides weighted agent selection based on reputation, latency, success rate, and availability |
| `p2p/settlement/` | On-chain USDC settlement for P2P tool invocations. `Service` handles EIP-3009 authorization-based transfers with exponential retry. `ReputationRecorder` interface for outcome tracking. Subscriber pattern for settlement notifications |

## `prompts/`

Expand Down
85 changes: 85 additions & 0 deletions docs/cli/a2a.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# A2A Commands

Commands for inspecting A2A (Agent-to-Agent) protocol configuration and verifying remote agent connectivity. See the [A2A Protocol](../features/a2a-protocol.md) section for detailed documentation.

```
lango a2a <subcommand>
```

---

## lango a2a card

Show the local A2A agent card configuration, including enabled status, base URL, agent name, and configured remote agents.

```
lango a2a card [--json]
```

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--json` | bool | `false` | Output as JSON |

**Example:**

```bash
$ lango a2a card
A2A Agent Card
Enabled: true
Base URL: http://localhost:18789
Agent Name: lango
Description: AI assistant with tools

Remote Agents (2)
NAME AGENT CARD URL
weather-agent http://weather-svc:8080/.well-known/agent.json
search-agent http://search-svc:8080/.well-known/agent.json
```

When A2A is disabled:

```bash
$ lango a2a card
A2A Agent Card
Enabled: false

No remote agents configured.
```

---

## lango a2a check

Fetch and display a remote agent card from a URL. Useful for verifying that a remote A2A agent is reachable and correctly configured before adding it to your configuration.

```
lango a2a check <url> [--json]
```

| Argument | Required | Description |
|----------|----------|-------------|
| `url` | Yes | URL of the remote agent card (e.g., `http://host/.well-known/agent.json`) |

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--json` | bool | `false` | Output as JSON |

**Example:**

```bash
$ lango a2a check http://weather-svc:8080/.well-known/agent.json
Remote Agent Card
Name: weather-agent
Description: Provides weather data and forecasts
URL: http://weather-svc:8080
DID: did:lango:02abc...
Capabilities: [weather, forecast]

Skills (2)
ID NAME TAGS
get-weather Get Weather [weather, location]
forecast 5-Day Forecast [weather, forecast]
```

!!! tip
Use `lango a2a check` before adding a remote agent to your configuration to verify connectivity and inspect its capabilities.
Loading