https://github.com/magicxor/pacos-agy-acp
AI-powered .NET Telegram bot that drives the agy (Google Antigravity) CLI agent via a Rust ACP adapter.
https://github.com/magicxor/pacos-agy-acp
acp agy agy-acp agy-cli ai-chatbot bot cli console-application csharp docker dotnet gemini google-ai markdown stdin telegram telegram-bot
Last synced: 14 days ago
JSON representation
AI-powered .NET Telegram bot that drives the agy (Google Antigravity) CLI agent via a Rust ACP adapter.
- Host: GitHub
- URL: https://github.com/magicxor/pacos-agy-acp
- Owner: magicxor
- License: mit
- Created: 2026-06-05T23:14:17.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-07-20T21:42:02.000Z (20 days ago)
- Last Synced: 2026-07-20T23:26:45.222Z (20 days ago)
- Topics: acp, agy, agy-acp, agy-cli, ai-chatbot, bot, cli, console-application, csharp, docker, dotnet, gemini, google-ai, markdown, stdin, telegram, telegram-bot
- Language: C#
- Homepage:
- Size: 604 KB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Pacos Telegram Bot
[](https://github.com/magicxor/pacos-agy-acp/actions/workflows/on_master_push.yml)
[](https://deepwiki.com/magicxor/pacos-agy-acp)
Pacos is a .NET-based Telegram bot designed to interact in group chats. It drives the agy (Google Antigravity) CLI agent through the `agy-acp` ACP adapter to produce chat responses, run tools, and deliver generated files.
*The alpaca was scientifically described by Carl Linnaeus in his System of Nature (1758) under the Latin name Camelus pacos.*

## Features
- **AI-Powered Chat**: Responds to mentions (e.g., "pacos", "пакос") or direct messages by driving the agy agent over ACP. Each chat gets its own working directory holding a persona steering file (`AGENTS.md`) and a set of agy Agent Skills (`.agents/skills//SKILL.md`) that carry the tool-specific instructions and are loaded on demand instead of on every turn.
- **Image Generation**: Generate or modify images via the `!drawx ` command. An optional source image can be supplied with the command or by replying to a message that contains one.
- **File Delivery**: The agent can return generated files (images, documents, etc.) by moving them into a per-turn output directory via the filemcp MCP server, which the bot then forwards back to the user.
- **Chat Management**:
- **Reset History**: Users can clear the agent's session for a specific chat with the `!resetx` command.
- **Language Identification**: Detects the language of incoming messages to tailor responses (using `NTextCat` with `Core14.profile.xml`).
- **Sandboxed Execution**: An enforced agy permission policy (written at startup) denies all shell commands and restricts the agent's file access to its per-chat workspace and the brain staging dir; file delivery is handled by the filemcp MCP server, not the shell. The real isolation boundary is the container (non-root user, restricted volume).
- **Asynchronous Processing**: Handles incoming Telegram updates and agent interactions asynchronously using a background task queue to ensure responsiveness.
## Core Technologies
- **Framework**: .NET (Worker Service)
- **Telegram API**: [Telegram.Bot](https://github.com/TelegramBots/telegram.bot) library
- **AI Agent**: agy ([Google Antigravity CLI](https://antigravity.google/docs/cli-using)), driven via the `agy-acp` [ACP adapter](https://github.com/openabdev/openab)
- **Logging**: NLog (configured via `nlog.config`)
- **Configuration**: Standard .NET configuration (e.g., `appsettings.json`, environment variables)
- **Language Detection**: `NTextCat`
## Configuration
The bot reads its settings from environment variables or an `appsettings.json` file under the `Pacos` section.
**Required:**
- `TelegramBotApiKey`: Your Telegram Bot API token.
- `AllowedChatIds`: An array of Telegram chat IDs where the bot is permitted to operate.
- `ChatModel`: The model name written into the agy permission policy (e.g. `Gemini 3.5 Flash (High)`).
**Optional:**
- `FallbackChatModel`: Model retried once when the primary model fails with a quota error (HTTP 429 / RESOURCE_EXHAUSTED). Pick one billed against a different quota pool than `ChatModel` (e.g. `Claude Sonnet 4.6 (Thinking)` when the primary is a Gemini model); the value must exactly match a label from `agy models`. Empty disables the fallback.
- `AgyAcpCommand`: Executable used to spawn the agy-acp adapter (default: `agy-acp`).
- `AgyAcpArgs`: Extra command-line arguments passed to the agy-acp process.
- `WorkingDirectoryRoot`: Root directory under which per-chat working directories are created (default: a folder under the system temp directory).
- `AgyExtraArgs`: Extra arguments forwarded to every underlying `agy` invocation (via `AGY_EXTRA_ARGS`).
- `GeminiApiKey`: Optional Gemini API key passed to the agy subprocess for non-interactive auth. When empty, agy relies on its own persisted OAuth credentials (e.g. `~/.gemini`).
- `PromptTimeoutSeconds`: Hard timeout for a single prompt round-trip to agy-acp (default: `300`).
- `SessionIdleTimeoutMinutes`: When a chat has been idle (no prompt to the agent) for longer than this, the next prompt starts a fresh session instead of resuming — and paying the tokens for — the stale conversation (default: `180`; `0` disables).
- `AgyCommandRuleMode`: Which set of agy command-permission rules to write (`denyall` (default) or `off`).
## Setup and Running
1. Ensure you have the .NET SDK and the `agy` / `agy-acp` executables available on `PATH`.
2. Configure the required settings (see **Configuration** section).
3. Create `Core14.profile.xml` (for NTextCat language identification) in the application's root directory.
4. Run the application:
```bash
dotnet run
```
When running in Docker, the agy state directory (`/home/agent/.gemini`) should be backed by a named volume so the agent's OAuth credentials and state persist across deployments (see the deploy workflow).
## Bot Commands
- `pacos, `: Engage in a conversation with the agent.
- `!drawx `: Generate an image based on the provided text prompt (optionally using an attached or replied-to image as the source).
- `!resetx`: Reset the agent's session for the current chat.