Agent Browser CLI
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
A skill your agent uses when adding a new messaging channel to Tel-Agent or changing an existing one — a transport under api/channels/, its official extension manifest, its settings card, tests…
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install Dpro-at/Tel-Agent channel-extension --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/channel-extension .claude/skills/channel-extension && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .claude/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extensionType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install Dpro-at/Tel-Agent channel-extension --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/channel-extension .agents/skills/channel-extension && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .agents/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install Dpro-at/Tel-Agent channel-extension --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/channel-extension .cursor/skills/channel-extension && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .cursor/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/Dpro-at/Tel-Agent.git --path .claude/skills/channel-extension--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install Dpro-at/Tel-Agent channel-extension --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/channel-extension .gemini/skills/channel-extension && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .gemini/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install Dpro-at/Tel-Agent channel-extensionInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/channel-extension .github/skills/channel-extension && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .github/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add Dpro-at/Tel-Agent --skill channel-extension -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install Dpro-at/Tel-Agent channel-extension --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/Dpro-at/Tel-Agent.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/channel-extension .opencode/skills/channel-extension && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "channel-extension" agent skill from https://github.com/Dpro-at/Tel-Agent/tree/main/.claude/skills/channel-extension into .opencode/skills/channel-extension/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "channel-extension", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
channel-extensionA skill your agent uses when adding a new messaging channel to Tel-Agent or changing an existing one — a transport under api/channels/, its official extension manifest, its settings card, tests…
Channel Extension is an agent skill from Dpro-at/Tel-Agent. Use when adding a new messaging channel to Tel-Agent or changing an existing one — a transport under api/channels/, its official extension manifest, its settings card, tests, health and docs. Covers the file checklist, the two inbound shapes (dial-out and the public door), the credential and signature rules that are not negotiable, the declarative setup descriptor the generic card draws from, and the test shape every channel ships with.
Its SKILL.md is about 4.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It works with Discord. The repository describes itself as: AI phone assistant | open-source. The licence is AGPL-3.0.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 931afa4. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
ruffpytestmypynpmnpxFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
developers.line.bizFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Channel Extension loads about 4.1k tokens when it runs. Until then it costs about 115 tokens; SKILL.md has 1,712 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from Dpro-at/Tel-Agent at commit 931afa4, republished under its AGPL-3.0 licence (© Dpro-at). 1,712 words, ~4,141 tokens.
.claude/skills/channel-extension/SKILL.md (or your agent's skills folder).You are adding a messaging channel to Tel-Agent. A channel is a route a customer
uses to reach a business — someone is typing on the other end. If nobody outside the
business is on the other end, it is an integration, not a channel, and it is reached
through the HTTP tool instead (Rule 5 in CLAUDE.md). Do not build it here.
Read first, in this order: CLAUDE.md (the contract), docs/SPEC.md §B9 (secrets)
and §B13 (channels), then api/channels/discord.py end to end. Discord is the model
every channel copies: a dial-out transport with a supervisor loop, an answering policy,
storage with dedup, and delivery-before-storage. For a channel that receives webhooks,
also read api/channels/meta_chat.py and api/routes/meta_chat_channels.py — that is
the public door, and its guards are the whole of this product's exposed surface.
Write everything from the platform's official documentation and from the shape of
the existing modules. Write it fresh. Never paste code from another product into this
repository, never name another product anywhere in it, and never add a runtime
dependency — httpx, websockets, cryptography and the standard library cover every
platform we ship.
One kind, one transport module, one manifest, one descriptor, one test file. In order:
| # | Path | What goes there |
|---|---|---|
| 1 | api/channels/<kind>.py | The transport. Module surface below. |
| 2 | api/extensions/builtin/<kind>.py | MANIFEST + register(context). Copy the Discord one; change slug, name, description. Category channels, origin official, scopes conversations.write, messages.read, messages.write, hooks message.received, ui_slots conversation.detail. |
| 3 | api/extensions/builtin/__init__.py | Append the module to BUILTIN. |
| 4 | api/models/conversation.py | The kind is already in CHANNEL_KINDS (one migration added every kind of this wave). If yours is not, add it and an Alembic revision that widens the channel_kind CHECK constraint — tests/test_migrations.py runs it on SQLite and PostgreSQL. |
| 5 | api/channels/generic.py | Add the module's import path to _DECLARED. The registry imports it on first read; that is what serves its card and its routes. |
| 6 | api/main.py | Dial-out channels: append transport.loop(sessionmaker) to background. Door channels: nothing — the generic public route dispatches by kind. |
| 7 | tests/test_<kind>_channel.py | The test file. Shape below. |
| 8 | web/components/brands/marks.tsx + source/<kind>.svg | The mark, when the platform has a logo. Record the source and licence in web/components/brands/README.md. A channel with no owner (SMS, IRC) gets a drawn glyph in web/components/shell/channel-mark.tsx. |
| 9 | web/app/[locale]/settings/settings.tsx | Add the kind to GENERIC_CHANNELS. The card draws itself from the descriptor. |
| 10 | locales/en/web.json | The display name under "channels". Other languages follow through the translation pipeline; do not touch thirty-four files. |
| 11 | docs/SPEC.md §B13, README.md icon row, docs/brand/channels/ | One row, one icon, one table line. |
Every module exposes the same names, so the generic route, the health rollup and the
tests can treat them alike. Signatures are the ones api/channels/discord.py has;
keep them.
KIND = "<kind>"
SETUP = Setup(...) # the descriptor, see below
INBOUND = "dial_out" # or "door"
def make_client() -> httpx.AsyncClient: ... # tests monkeypatch this
async def probe(client, credentials: dict[str, str]) -> str:
...
# "Test connection". Returns the identity the platform reports (bot name, number,
# account) — the card shows it. Raises ChannelRefused on a bad credential.
async def send_text(client, credentials, target: str, text: str) -> None: ...
def message_text(event, identity) -> str | None: ... # the answering policy: None = ignore
async def ingest(db, channel, event) -> int | None:
...
# store one inbound line; None when it was a duplicate or not for us
async def respond(sessionmaker, channel_id: int, message_id: int) -> None: ...
def schedule_reply(sessionmaker, channel_id: int, message_id: int) -> None: ...
# optional
def credentials_changed(channel_id: int) -> None:
...
# What the module is told after the operator writes this channel's fields, so it can
# drop anything it cached on the strength of the old ones — an access token bought
# with a secret that has just been replaced would otherwise keep working until it
# expired, which is a rotation that did not take effect. A module that caches nothing
# declares nothing; `api/routes/generic_channel.py` calls it only when it is there.
def reply_target(conversation) -> str | None:
...
# The address `send_text` needs for this thread, when it is not the conversation's
# own `external_id` — a room id, a thread key, a mailbox. Declare nothing and
# `generic.reply_target_of` falls back to `external_id`. It is what the human
# takeover route delivers to as well, so a channel that answers somewhere other
# than where the customer wrote from owes this one function and nothing else.
# dial-out only
async def loop(sessionmaker) -> None: ... # the supervisor, reconciles every 15 s
# door only
async def receive(db, channel, request: Request) -> Response:
...
# verify, dedup, store, schedule, acknowledge. One refusal for every failure.credentials is the decrypted JSON of Channel.credentials_encrypted — a dict keyed by
the descriptor's field names. Never read it on the inbound hot path for anything other
than a signature check; per-channel state that every message needs lives in
settings_json, which is plain.
api/channels/generic.py holds the half of a transport that is the same on every
channel. A declarative channel writes the platform-specific half only: its descriptor,
its signature check, probe, send_text, message_text, ingest, and its receive
or loop. split_text is a line delegating to split_on_words below. Everything below
is already written.
| Helper | What it does |
|---|---|
channels() | The registry, populated on first read. module_for(kind) and dial_out_modules() go through it, so no import order can change what an installation has. Never read CHANNELS directly. |
public_url_for(request, settings) | The address the platform called, for a signature computed over it. PUBLIC_BASE_URL when the installation has one, else the forwarded headers — the one place in this product where those are read, and the reasoning is in the function. The settings card builds its webhook_url on the same base, so the two cannot disagree. |
conversation_for(db, channel, external_id, title=None) | This customer's open thread, and whether it was just started. |
store_line(db, conversation, role, text, language=None) | One line into the transcript. |
seen_before(conversation, kind, message_id) | Dedup. A ring of the last 32 platform ids in state_json[kind], because a platform does not retry in order. |
announce(db, channel, conversation, message, started) | The conversation.started and message.received hooks. |
preview(text) | One line of a customer's words, for a notification. |
reply_target_of(module, conversation) | Where a reply goes: the module's reply_target, else external_id. |
split_on_words(text, limit) | The cut every channel shares: pieces no longer than limit, never inside a word, never silently short, and a single word longer than the limit cut rather than dropped. A module's split_text is one line handing this its own MESSAGE_MAX. |
deliver(module, client, credentials, target, text) | One answer out, cut into the platform's messages through the module's split_text. |
schedule_reply(sessionmaker, module, channel_id, message_id) | The answer as its own task, held so it cannot be collected mid-reply. |
respond(sessionmaker, module, channel_id, message_id) | The whole answer path: its own session, takeover read before generating and again before sending, delivery before storage, health timing. |
A module still exposes respond and schedule_reply itself — the registry requires
them — but each is one line handing the shared one this module:
def _self() -> ModuleType:
return sys.modules[__name__]
async def respond(sessionmaker, channel_id: int, message_id: int) -> None:
await generic.respond(sessionmaker, _self(), channel_id, message_id)The human takeover route needs no branch per channel: api/routes/conversations.py
delivers through the registry for any kind on it.
The card, the write route and the test button are generic. What makes one channel's card differ from another's is this object, declared once in the transport module:
from api.channels.setup import Field, Setup
SETUP = Setup(
kind="line",
title="LINE",
note="An official account from your own LINE Developers console answers people who message it.",
guide_url="https://developers.line.biz/en/docs/messaging-api/getting-started/",
fields=(
Field(
"channel_secret",
"Channel secret",
secret=True,
help="From the Basic settings tab of your channel.",
),
Field(
"channel_access_token",
"Channel access token",
secret=True,
help="Issue a long-lived token on the Messaging API tab.",
),
),
verified_live=False, # True once a real message has gone through on a customer's account
)secret=True fields are write-only: the API returns a masked preview (last four
characters), never the value. secret=False fields are returned as stored.required=False fields may be left empty. The card shows them under "Optional".label and help are what the card shows unless a locale key
ch_<kind>_<field> / ch_<kind>_<field>_help exists. Do not add locale keys for a
new channel yourself; the translation pipeline does.verified_live=False prints "built against the published API, not yet verified with
a live account" on the card. It is honest and it stays until someone flips it after
a real message.Channel.webhook_path.The generic routes are GET /api/channels/{kind} (descriptor + state),
PUT /api/channels/{kind} (fields, enabled), POST /api/channels/{kind}/test, and for
doors GET|POST /public/{kind}/{webhook_path}. They live in
api/routes/generic_channel.py and api/routes/public_channel.py; you do not write
routes for a new channel.
Credentials — §B9. Encrypted at rest in Channel.credentials_encrypted, one JSON
object for all of a channel's secrets. Write-only: an empty string clears the field, a
value starting with • or * is an echoed mask and is ignored, anything else is stored.
Clearing the last required secret switches the channel off. Storing requires the
installation's encryption key (409 encryption_key_missing without it). Never log a
credential, never return one, never put one in a URL. Every write is audited.
The customer's own application. Tel-Agent holds no shared platform app. Every credential comes from the customer's own developer account. If a platform only works through an application the vendor owns, it cannot be a Tel-Agent channel.
The door — for every channel that receives webhooks.
secrets.token_urlsafe(24)), unique per channel,
stored in Channel.webhook_path. The route is /public/{kind}/{webhook_path}.hmac.compare_digest. A JWT is verified against the issuer's published keys
with cryptography, checking iss, aud, exp. No signature scheme, no channel.not_recognised. The door leaks
nothing about what exists behind it.Answering policy. A direct message is always answered. A group, room, channel or space message is answered only when the bot is addressed, and the mention is stripped before the text reaches the model. A message from the bot itself, or from another bot, is never answered.
Delivery before storage. respond() generates the whole reply, delivers it, and
only then writes the agent line. If delivery raises, nothing is written — a transcript
must never show an answer the customer did not receive. Human takeover is checked
before generating and again before sending.
Reconnection. Dial-out loops reconnect with exponential backoff from 5 s to 300 s
and report their state through api/channels/health.py so the health page can say
"connected" or "reconnecting" truthfully.
Text limits. Every platform has one. Split on word boundaries at the platform's limit; never truncate silently.
Nothing new in pyproject.toml. If you believe a platform genuinely cannot be done
without an SDK, stop and say so in the report instead of adding it.
tests/test_<kind>_channel.py, modelled on tests/test_discord_channel.py. A fake
platform, not mocked functions:
class FakeLine:
def __init__(self) -> None:
self.sent: list[dict] = []
self.refuse = False
def handler(self, request: httpx.Request) -> httpx.Response: ... # route by path
def client(self) -> httpx.AsyncClient:
return httpx.AsyncClient(
base_url="https://line.test", transport=httpx.MockTransport(self.handler)
)The stage fixture builds a workspace, a channel row with credentials, three users at
admin / reception / viewer, monkeypatches make_client, and starts the real app.
Copy it.
Every channel's file has at least these, named for what they prove:
Run the suite for your file and the shared ones, then the gate:
pytest tests/test_<kind>_channel.py tests/test_channel_health.py tests/test_extensions.py -q
ruff check . && ruff format --check . && mypy .
npm --prefix web run lint && npx --prefix web tsc --noEmitfeat(channels): add <kind>.© Dpro-at, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/channel-extension of Dpro-at/Tel-Agent.
Open the folder on GitHubat commit 931afa4
Channel Extension next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Channel Extension this skillDpro-at/Tel-Agent | 1.1k | — | ~4.1k | Automated safety check: Pass | AGPL-3.0 | |
| Agent Browser CLIvercel-labs/agent-browser | 44k | 24 repos | ~864 | Automated safety check: Pass | Apache-2.0 | |
| Electron App Automationvercel-labs/agent-browser | 44k | 5 repos | ~1.7k | Automated safety check: Pass | Apache-2.0 | |
| Claude To Imop7418/Claude-to-IM-skill | 2.9k | — | ~3.4k | Automated safety check: Notes | MIT | |
| Sap Extension Creatorheshengtao/super-agent-party | 2.7k | — | ~6k | Automated safety check: Pass | AGPL-3.0 | |
| Libtv Videonexu-io/nexu | 3.3k | — | ~3.5k | Automated safety check: Pass | MIT |
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
vercel-labs/agent-browser
Automates Electron desktop apps such as VS Code, Slack or Discord by connecting agent-browser to their Chrome DevTools Protocol port.
op7418/Claude-to-IM-skill
Bridge THIS Claude Code or Codex session to Telegram, Discord, Feishu/Lark, QQ, or WeChat so the user can chat with Claude from their phone.
heshengtao/super-agent-party
Create Super Agent Party (SAP) extensions. An agent skill from heshengtao/super-agent-party.
nexu-io/nexu
Seedance 2.0 video & image generation via LibTV Gateway - AI text-to-video, image-to-video, video continuation, style transfer, and text-to-image using Seedance 2.0 model.
TinyAGI/tinyagi
Send a proactive message to a paired user via their channel (Discord, Telegram, or WhatsApp).
Dpro-at/Tel-Agent
A skill your agent uses when contributing to Tel-Agent - picking an issue to work on, setting up the repository for the first time, starting or finishing a task, opening a pull request, or asking…
Works with
A skill your agent uses when adding a new messaging channel to Tel-Agent or changing an existing one — a transport under api/channels/, its official extension manifest, its settings card, tests…. Channel Extension is an agent skill from Dpro-at/Tel-Agent. Use when adding a new messaging channel to Tel-Agent or changing an existing one — a transport under api/channels/, its official extension manifest, its settings card, tests, health and docs.
Channel Extension fits situations like: adding a new messaging channel to Tel-Agent; changing an existing one — a transport under api/channels/; its official extension manifest; its settings card.
Run `npx skills add Dpro-at/Tel-Agent --skill channel-extension -a claude-code`. Or copy the skill folder (.claude/skills/channel-extension in Dpro-at/Tel-Agent) into .claude/skills/channel-extension in your project. Claude Code loads it when a task matches its description.
Run `npx skills add Dpro-at/Tel-Agent --skill channel-extension -a codex`. Or copy the skill folder (.claude/skills/channel-extension in Dpro-at/Tel-Agent) into .agents/skills/channel-extension in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add Dpro-at/Tel-Agent --skill channel-extension -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/channel-extension, .gemini/skills/channel-extension, .github/skills/channel-extension and .opencode/skills/channel-extension in your project.
Going by SKILL.md and its folder, Channel Extension needs the command-line tools its instructions call (ruff, pytest, mypy, npm and npx). Our summary lists: Python 3.
SKILL.md names 1 domain. In commands or code: developers.line.biz; the agent is likely to contact it when it follows the instructions. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Channel Extension is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.1k tokens (SKILL.md is roughly 17k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Channel Extension: Agent Browser CLI (vercel-labs/agent-browser, 44k stars), Electron App Automation (vercel-labs/agent-browser, 44k stars), Claude To Im (op7418/Claude-to-IM-skill, 2.9k stars) and Sap Extension Creator (heshengtao/super-agent-party, 2.7k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
Dpro-at (a GitHub organization) maintains it in Dpro-at/Tel-Agent, which has 1,097 GitHub stars. The repository holds 2 skills in this directory. The repository was last updated on October 8, 2026.
Source: Dpro-at/Tel-Agent on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.