← Back to Blog
Permission Control and Security in OpenACP
12 min read security permissions self-hosted

Permission Control and Security in OpenACP: A Complete Guide

When you give an AI coding agent the ability to read your files, execute commands, and modify your codebase, security is not optional -- it is foundational. OpenACP was designed from the ground up with a layered security model that puts you in control of every action your agent takes. This guide walks through every security feature in detail, from the interactive permission gate to the self-hosted data model that ensures your code never leaves your infrastructure.

Why Security Matters for AI Agent Bridges

AI coding agents like Claude Code, Gemini CLI, and Codex CLI are incredibly powerful. They can write code, run shell commands, create and delete files, install packages, and interact with external services. That power, when exposed through a messaging platform like Telegram, Discord, or Slack, introduces a new category of risk that traditional development workflows never had to consider.

Consider this scenario: you send a message in Telegram asking your AI agent to "clean up the test directory." Without proper guardrails, the agent might interpret that as rm -rf ./tests/ and execute it before you have any chance to review. Or imagine a shared team Slack workspace where any member could spin up an agent session and start modifying production configuration files. These are not hypothetical risks -- they are exactly the kind of situations that OpenACP's security model is designed to prevent.

The security challenge breaks down into several distinct concerns: who can interact with the agent, what the agent is allowed to do, how long sessions can remain active, and where the data flows. OpenACP addresses each of these with specific, configurable mechanisms that we will explore in this guide.

The Permission Gate: Approve or Deny Every Action

At the heart of OpenACP's security model is the permission gate. When an AI agent wants to perform a potentially dangerous action -- executing a shell command, writing to a file, or installing a package -- OpenACP intercepts that request and sends you an interactive message with Approve and Deny buttons directly in your messaging app.

This is not a simple confirmation dialog. The permission gate shows you exactly what the agent wants to do, including the full command text or file path, before you make your decision. Here is how the flow works:

  1. You send a request to your AI agent via Telegram, Discord, or Slack
  2. The agent processes your request and determines it needs to perform a privileged action
  3. OpenACP intercepts the action via the Agent Client Protocol
  4. A permission request message appears in your chat with the full action details
  5. You tap Approve or Deny
  6. If approved, the agent proceeds; if denied, the agent receives an error and adapts its approach

The permission gate has a 10-minute timeout. If you do not respond within that window, the action is automatically denied. This prevents situations where a pending permission could be approved hours later in a completely different context.

// The permission gate is implemented in the Session class
// When the agent subprocess requests a tool execution:

async handleToolPermission(tool: string, args: Record<string, unknown>) {
  const message = await this.adapter.sendPermissionRequest({
    tool,
    args,
    sessionId: this.id,
    timeout: 10 * 60 * 1000  // 10 minutes
  });

  // Wait for user interaction (approve/deny button)
  const result = await this.waitForPermissionResponse(message.id);

  if (result === 'denied' || result === 'timeout') {
    throw new PermissionDeniedError(tool);
  }

  return true;
}

The permission gate integrates natively with each platform's UI. On Telegram, you see inline keyboard buttons. On Discord, you get interactive button components. On Slack, Block Kit actions appear inline. The experience feels natural regardless of your platform.

What Gets Gated

Not every action triggers a permission request. Reading files and providing text responses typically pass through without interruption. The gate is triggered by actions that could modify your system:

The exact set of gated actions depends on which AI agent you are using, since each agent defines its own tool set through ACP. OpenACP respects the agent's tool definitions and gates any tool that the agent marks as requiring confirmation.

Auto-Approve: "Dangerous Mode"

For experienced users who understand the risks, OpenACP supports an auto-approve mode that bypasses the permission gate entirely. This is sometimes called "dangerous mode" because it allows the agent to execute any action without explicit approval.

Auto-approve is useful in specific scenarios: rapid prototyping on throwaway branches, working with sandboxed environments, or when you are pair-programming with the agent and can see every action in real-time through the streaming output.

To enable auto-approve, you can set it in your configuration:

{
  "autoApprove": true
}

Or pass it as an environment variable:

OPENACP_AUTO_APPROVE=true openacp
Warning: Auto-approve mode disables the primary safety mechanism in OpenACP. Only use it in isolated environments where unintended modifications cannot cause damage. Never enable auto-approve on production systems or shared development machines without understanding the full implications.

Even with auto-approve enabled, other security layers -- allowed user IDs, session limits, and session timeouts -- remain active. Auto-approve only affects the permission gate; it does not disable access control.

Allowed User IDs: Controlling Who Can Access the Agent

The allowedUserIds configuration is your first line of defense. It defines exactly which users on each platform are permitted to interact with the agent. Any message from a user not in this list is silently ignored -- no error message, no acknowledgment, no information leakage.

// ~/.openacp/config.json
{
  "telegram": {
    "token": "your-bot-token",
    "allowedUserIds": [123456789, 987654321]
  },
  "discord": {
    "token": "your-bot-token",
    "allowedUserIds": ["112233445566778899", "998877665544332211"]
  },
  "slack": {
    "appToken": "xapp-...",
    "botToken": "xoxb-...",
    "allowedUserIds": ["U01ABCDEF", "U02GHIJKL"]
  }
}

Finding Your User ID

Each platform has a different way to find user IDs:

Telegram: Send a message to @userinfobot or use the /getid command in many bot frameworks. Your numeric user ID is different from your username.

Discord: Enable Developer Mode in Settings > Advanced, then right-click your name and select "Copy User ID." Discord IDs are snowflake strings like "112233445566778899".

Slack: Click on your profile, then "More" > "Copy Member ID." Slack user IDs follow the format "U01ABCDEF".

If you leave allowedUserIds empty or omit it, the behavior depends on the platform adapter. By default, an empty list means no one can access the agent, which is the safest default. You must explicitly add user IDs to grant access.

Team Access Patterns

For team environments, you will typically want to add multiple user IDs. Here are some common patterns:

Session Limits and Timeouts

Even authorized users should not be able to consume unlimited resources. OpenACP implements two key constraints: maximum concurrent sessions and session timeouts.

Max Concurrent Sessions

The maxConcurrentSessions setting (default: 20) controls how many AI agent sessions can be active at the same time. Each session represents a running agent subprocess with its own memory, CPU, and file system access.

{
  "maxConcurrentSessions": 5
}

When the limit is reached, new session requests are queued or rejected with a clear error message. This prevents both accidental resource exhaustion (a user accidentally spawning dozens of sessions) and potential denial-of-service scenarios.

For personal use, a limit of 3-5 concurrent sessions is typically sufficient. For team environments with multiple users, you might set it to 10-20, depending on your server's capacity. Each AI agent session consumes roughly 200-500MB of RAM, so a server with 16GB of RAM can comfortably handle 20-30 concurrent sessions.

Session Timeout

Every session has a maximum lifetime, configured via sessionTimeout (default: 60 minutes). After this period, the session is automatically terminated, the agent subprocess is killed, and any temporary resources are cleaned up.

{
  "sessionTimeout": 30  // 30 minutes, in minutes
}

Session timeouts serve multiple security purposes:

When a session approaches its timeout, OpenACP can send a warning message to the user. When the timeout expires, the session is gracefully terminated -- the agent subprocess receives a SIGTERM, has a brief grace period to clean up, and then is forcefully killed if it has not exited.

The Self-Hosted Data Model

Perhaps the most important security feature of OpenACP is one that requires no configuration at all: it runs entirely on your infrastructure.

Unlike cloud-hosted solutions, OpenACP never routes your code, conversations, or file contents through third-party servers. The data flow is direct:

  1. Your message goes from your messaging app to OpenACP on your machine (or your server)
  2. OpenACP passes the message to the AI agent subprocess running locally
  3. The AI agent communicates with its API provider (e.g., Anthropic, Google, OpenAI) using your own API keys
  4. Responses flow back through the same local path to your messaging app

No intermediate proxy. No cloud relay. No data storage on external servers. The only network traffic that leaves your machine is between the AI agent and its API provider -- and that traffic uses your own API keys, your own rate limits, and your own billing.

This architecture has profound security implications:

Comparison: Self-Hosted vs. Cloud-Hosted

Aspect OpenACP (Self-Hosted) Cloud Solutions
Code exposure Never leaves your machine Transmitted to cloud servers
API keys Stored locally only May be stored by provider
Conversation logs Local filesystem only Stored on provider servers
Network control Full visibility and control Provider-managed
Compliance You manage compliance Depends on provider
Cost Free (MIT license) Subscription fees

Configuration Security

OpenACP stores its configuration at ~/.openacp/config.json. This file contains sensitive information including bot tokens, API keys, and allowed user IDs. Proper file permissions are essential.

# Set restrictive permissions on the config directory
chmod 700 ~/.openacp
chmod 600 ~/.openacp/config.json

The configuration is validated using Zod schemas at startup. If your configuration contains invalid values -- a malformed token, a non-numeric user ID where a number is expected, or an unknown property -- OpenACP will refuse to start and provide a clear error message indicating exactly what is wrong.

// Zod schema validation ensures type safety at runtime
const ConfigSchema = z.object({
  telegram: z.object({
    token: z.string().min(1, "Telegram token is required"),
    allowedUserIds: z.array(z.number().int().positive()),
  }).optional(),
  discord: z.object({
    token: z.string().min(1, "Discord token is required"),
    allowedUserIds: z.array(z.string().min(1)),
  }).optional(),
  maxConcurrentSessions: z.number().int().min(1).max(100).default(20),
  sessionTimeout: z.number().int().min(1).max(1440).default(60),
  autoApprove: z.boolean().default(false),
});

This schema validation prevents a common class of security bugs: misconfigured settings that silently weaken security. If you accidentally set maxConcurrentSessions to -1 or allowedUserIds to a string instead of an array, the application will not start.

Environment Variable Overrides

Every configuration option can be overridden via environment variables using the OPENACP_ prefix. This is particularly useful for deployment scenarios where you want to keep secrets out of configuration files:

# Bot tokens via environment
export OPENACP_TELEGRAM_TOKEN="your-telegram-bot-token"
export OPENACP_DISCORD_TOKEN="your-discord-bot-token"
export OPENACP_SLACK_APP_TOKEN="xapp-..."
export OPENACP_SLACK_BOT_TOKEN="xoxb-..."

# Security settings via environment
export OPENACP_MAX_CONCURRENT_SESSIONS=10
export OPENACP_SESSION_TIMEOUT=30
export OPENACP_AUTO_APPROVE=false

# Then start OpenACP
openacp

Environment variables take precedence over config.json values. This layering allows you to have a base configuration file with non-sensitive defaults while injecting secrets at runtime through environment variables, Docker secrets, Kubernetes config maps, or your CI/CD system's secret management.

Using .env Files

For local development, you can use a .env file in your working directory:

# .env file (add to .gitignore!)
OPENACP_TELEGRAM_TOKEN=123456:ABC-DEF...
OPENACP_TELEGRAM_ALLOWED_USER_IDS=123456789,987654321
OPENACP_SESSION_TIMEOUT=45
OPENACP_AUTO_APPROVE=false
Important: Always add .env files to your .gitignore. Committing bot tokens or API keys to version control is one of the most common security mistakes in software development. OpenACP's openacp doctor command will warn you if it detects a .env file that might be tracked by git.

Doctor Diagnostics and Security Checks

OpenACP includes a built-in diagnostic command, openacp doctor, that checks your setup for common security issues and misconfigurations:

$ openacp doctor

OpenACP Doctor
==============

[PASS] Node.js version: v22.5.0 (>= 20 required)
[PASS] Config file found: ~/.openacp/config.json
[PASS] Config file permissions: 600 (restrictive)
[PASS] Config directory permissions: 700 (restrictive)
[PASS] Config validates against schema
[WARN] Auto-approve is enabled - all actions will be auto-approved
[PASS] Telegram token format valid
[PASS] Allowed user IDs configured for Telegram
[PASS] Max concurrent sessions: 10 (reasonable)
[PASS] Session timeout: 60 minutes
[INFO] No .env file detected in working directory
[PASS] No secrets detected in git-tracked files

The doctor command checks for:

Running openacp doctor before your first deployment and periodically thereafter is a best practice that can catch configuration drift and accidental security regressions.

Security Best Practices

Based on the security features described above, here is a comprehensive checklist for securing your OpenACP deployment:

1. Principle of Least Privilege

Only add user IDs for people who genuinely need agent access. For team environments, consider running separate OpenACP instances for different trust levels rather than giving everyone the same access.

2. Keep Auto-Approve Disabled

The permission gate exists for good reason. The few seconds it takes to tap "Approve" is a small price for the safety of knowing exactly what the agent is doing. Reserve auto-approve for isolated sandbox environments only.

3. Use Reasonable Timeouts

The default 60-minute session timeout is appropriate for most use cases. If your typical coding sessions are shorter, reduce it. Shorter timeouts mean smaller windows of exposure.

4. Secure Your Configuration

# Recommended file permissions
chmod 700 ~/.openacp
chmod 600 ~/.openacp/config.json

# Use environment variables for secrets in production
# Never commit tokens to version control
# Use .gitignore for .env files

5. Run Behind a Firewall

When running OpenACP on a server, ensure that the REST API port (21420) is not exposed to the public internet unless you specifically need external access. Use firewall rules or bind the API to localhost:

# Only allow local access to the API
iptables -A INPUT -p tcp --dport 21420 -s 127.0.0.1 -j ACCEPT
iptables -A INPUT -p tcp --dport 21420 -j DROP

6. Monitor Sessions

OpenACP uses Pino for structured logging. Enable log output and review it periodically for unusual patterns:

# Start with verbose logging
LOG_LEVEL=debug openacp 2>&1 | tee /var/log/openacp.log

# Search for permission denials
grep "permission_denied" /var/log/openacp.log

# Search for unauthorized access attempts
grep "unauthorized" /var/log/openacp.log

7. Use Separate Bot Tokens per Environment

Never share bot tokens between development and production environments. Create separate bots for each environment so that development activity cannot accidentally affect production, and compromised development tokens do not grant production access.

8. Keep OpenACP Updated

Security patches are released through npm. Regularly update to the latest version:

npm update -g @openacp/cli

9. Review Agent Capabilities

Different AI agents have different tool sets. Before connecting a new agent through OpenACP, review what tools it exposes through ACP. An agent that only has read access to your codebase poses different risks than one that can execute arbitrary shell commands.

10. Use Working Directory Isolation

Start OpenACP sessions in specific project directories rather than your home directory. This limits the agent's file system access to the relevant project:

# Good: limited scope
cd ~/projects/my-app && openacp

# Risky: full home directory access
cd ~ && openacp

Security Architecture: How It All Fits Together

Understanding how OpenACP's security layers interact is important for configuring them effectively. Here is the complete request lifecycle from a security perspective:

  1. Message received from messaging platform (Telegram/Discord/Slack)
  2. User ID check: Is the sender in allowedUserIds? If not, silently ignore the message.
  3. Session limit check: Are we at maxConcurrentSessions? If so, reject with an error.
  4. Session creation: A new agent subprocess is spawned in the configured working directory.
  5. Message forwarded to the agent via ACP.
  6. Agent processes the message and determines required actions.
  7. Permission gate: For privileged actions, send approve/deny to user (unless auto-approve is on).
  8. Action execution: If approved, the agent performs the action.
  9. Response streaming: Results stream back to the user in the messaging app.
  10. Timeout monitoring: Session is terminated if sessionTimeout is exceeded.

Each layer is independent. Even if one layer is misconfigured (say, auto-approve is accidentally enabled), the other layers still provide protection. A user not in allowedUserIds still cannot access the agent. Session limits still prevent resource exhaustion. Timeouts still clean up abandoned sessions.

This defense-in-depth approach means that no single misconfiguration can completely compromise your security. You would need to simultaneously disable the permission gate, add unauthorized users, remove session limits, and set infinite timeouts to create a fully unprotected deployment -- and OpenACP's Zod validation would flag most of those configurations as invalid anyway.

Wrapping Up

Security in OpenACP is not an afterthought bolted onto an existing system. It is woven into the architecture from the protocol layer (ACP permission gates) through the application layer (user access control, session management) to the deployment layer (self-hosted, environment variable secrets, file permissions).

The key takeaways are: always configure allowedUserIds, keep auto-approve disabled unless you have a specific reason to enable it, set reasonable session limits and timeouts, secure your configuration files, and run openacp doctor regularly to catch misconfigurations before they become vulnerabilities.

OpenACP gives you the convenience of controlling AI coding agents from your messaging app without sacrificing the security guarantees you need for professional software development.

Secure AI Agents from Your Chat

Install OpenACP and start coding with permission-gated AI agents on Telegram, Discord, or Slack.

npm install -g @openacp/cli && openacp