TACIT: Tracked Agent Capabilities In Types

by lampepfl

387 downloads Not rated yet

About

TACIT (Tracked Agent Capabilities In Types) is a safety harness for AI agents. Instead of calling tools directly, agents write code in Scala 3 with capture checking: a type system that statically tracks capabilities and enforces that agent code cannot forge access rights, cannot

Explore

Paper: Tracking Capabilities for Safer Agents (arXiv:2603.00991)

TACIT (Tracked Agent Capabilities In Types) is a safety harness for AI agents.
Instead of calling tools directly, agents write code in Scala 3 with capture checking: a type system that statically tracks capabilities and enforces that agent code cannot forge access rights, cannot perform effects beyond its budget, and cannot leak information from pure sub-computations.
It provides an MCP interface, so that it can be easily used by all MCP-compatible agents.

TACIT Framework Overview

The framework has three main components:

- Scala 3 compiler. Agent-submitted code is validated and type-checked with capture checking enabled in safe mode, which enforces a capability-safe language subset.
- Scala REPL. A local REPL instance executes compiled code and manages state across interactions. Supports both stateless one-shot execution and stateful sessions.
- Capability safety library. A typed API that serves as the sole gateway through which agent code interacts with the real world: file system, process execution, network, and sub-agents. The library is extensible: add new capabilities by modifying only the library code, without changing the MCP server itself.

TACIT's type system provides three safety guarantees that hold regardless of whether the agent is misaligned, hallucinating, or under prompt injection attack:

| Property | What it means |
|----------|---------------|
| Capability safety | Capabilities cannot be forged or forgotten. The agent can only access resources through capabilities explicitly granted to it. |
| Capability completeness | Capabilities regulate all safety-relevant effects. The agent interacts with the world only through its granted capabilities. |
| Local purity | Specific computations can be enforced as side-effect-free. This prevents information leakage when agents process classified data. |

The library exposes three capability request methods, each scoping access to a block. Capabilities cannot escape their scoped block. This is enforced at compile time by the capture checker.

// File system: scoped to a root directory
requestFileSystem("/tmp/work") {
  val f = access("data.txt")
  f.write("hello")
  val lines = f.readLines()
  grep("data.txt", "hello")
  find(".", ".txt")
}

// Process execution: scoped to an allowlist of commands
requestExecPermission(Set("ls", "cat")) {
val result = exec("ls", List("-la"))
println(result.stdout)
}

// Network: scoped to an allowlist of hosts
requestNetwork(Set("api.example.com")) {
val body = httpGet("https://api.example.com/data")
httpPost("https://api.example.com/submit", """{"key":"value"}""")
}

// Add a result type
case class QueryResult(columns: List[String], rows: List[List[String]])

// Add a capability class
class DatabasePermission(val connectionString: String) extends caps.SharedCapability

// Add methods to the Interface trait
trait Interface:
// ... existing methods ...

def requestDatabaseT(op: DatabasePermission^ ?=> T)(using IOCapability): T

def query(sql: String)(using DatabasePermission): QueryResult

Key points:
- The capability class must extend caps.SharedCapability. This is what enables Scala 3's capture checker to prevent the capability from escaping its scoped block.
- The request
method takes a block op that receives the capability as a context parameter (?=>). The ^ mark means the capability is tracked by the capture checker.
- Operation methods (like query) take the capability as a using parameter, so they can only be called inside the corresponding request* block.

Quick Start

TACIT provides a standard MCP server that communicates via JSON-RPC over stdio. It works with any MCP-compatible agent, including Claude Code, OpenCode, GitHub Copilot, and others.

Requires JDK 17+

execute_scala

`code`

execute_in_session

`session_id`, `code`

delete_repl_session

`session_id`

| Tool | Parameters | Description |
|------|-----------|-------------|
| execute_scala | code | Execute a Scala snippet in a fresh REPL (stateless) |
| create_repl_session | - | Create a persistent REPL session, returns session_id |
| execute_in_session | session_id, code | Execute code in an existing session (stateful) |
| list_sessions | - | List active session IDs |
| delete_repl_session | session_id | Delete a session |
| show_interface | - | Show the full capability API reference |

Paper: Tracking Capabilities for Safer Agents (arXiv:2603.00991)

TACIT (Tracked Agent Capabilities In Types) is a safety harness for AI agents.
Instead of calling tools directly, agents write code in Scala 3 with capture checking: a type system that statically tracks capabilities and enforces that agent code cannot forge access rights, cannot perform effects beyond its budget, and cannot leak information from pure sub-computations.
It provides an MCP interface, so that it can be easily used by all MCP-compatible agents.

TACIT Framework Overview

The framework has three main components:

- Scala 3 compiler. Agent-submitted code is validated and type-checked with capture checking enabled in safe mode, which enforces a capability-safe language subset.
- Scala REPL. A local REPL instance executes compiled code and manages state across interactions. Supports both stateless one-shot execution and stateful sessions.
- Capability safety library. A typed API that serves as the sole gateway through which agent code interacts with the real world: file system, process execution, network, and sub-agents. The library is extensible: add new capabilities by modifying only the library code, without changing the MCP server itself.

Quick Start

TACIT provides a standard MCP server that communicates via JSON-RPC over stdio. It works with any MCP-compatible agent, including Claude Code, OpenCode, GitHub Copilot, and others.

Requires JDK 17+

1. Download Prebuilt Release JARs (Recommended)

Use the release download script to get started quickly (no local build required).
It will download the latest server and library JARs from GitHub releases and place them in the current directory.

```bash

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.