create sandboxed rich-text telegram agents with a single config file
run
needs deno.
deno task start my-agent.yaml
config
this example is a research paper reader:
name: my-agent telegram_token: "123456:ABC-DEF..." anthropic_api_key: "sk-ant-..." allowed_usernames: - your-username model: claude-opus-4-8 # optional system: | # optional — defines what the agent is you are a research paper reader assistant. download all (html) papers you read and store them. when embedding a figure, only use real image urls from arxiv.org. sandbox: # optional — omit to deny all net: ["arxiv.org"] # hosts, not urls write: ["./papers"] env: false
required: telegram_token, anthropic_api_key, allowed_usernames. the
system prompt is what turns the same engine into a paper reader, a maps
helper, a coding assistant, etc. — telegram formatting and the agent's sandbox
permissions are explained to it automatically, so system only needs the
persona.
the yaml holds secrets. don't commit it.
sandbox
the agent's one tool is run_javascript, which runs in a deno subprocess. each
sandbox entry maps to a deno --allow-* flag on that subprocess:
true→ allow (unrestricted)[list]→ allow only those hosts/paths (e.g.--allow-net=a.com,b.com)false/ omitted → denied
omit the whole sandbox block and generated js gets zero permissions. denied
operations fail with a deno permission error returned to the agent. the agent is
told its exact permissions in its system prompt, so it knows what it can and
can't do.
rich formatting
replies are sent with telegram's sendRichMessage, so the agent's
github-flavored markdown renders natively: headings, bold/italic,
strikethrough, lists, task lists, blockquotes, code, fenced code blocks,
links, footnotes, latex formulas ($x^2$), tables, and media blocks
(, including maps via <tg-map .../>). a bad media url is stripped
and the message is retried so formatting never gets dropped wholesale.
features
- typing indicator while it works
- native rich-text replies (graceful fallback)
- per-user conversation history (in memory, resets on restart)
- streamed under the hood so long replies don't time out
