Observed since 20 Oct, 18:10 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
aceteam-nodes
Workflow node types for aceteam-workflow-engine
A bundle of workflow node types for aceteam-workflow-engine: LLM text generation, HTTP requests, authenticated browser fetch, and XPath extraction.
This is a node-source package, not a runner. It ships no CLI and no execution
engine — it advertises its nodes through the aceteam_workflow_engine.nodes
entry-point group, and an operator mounts them into an engine with
wengine install aceteam-nodes. The engine then executes them.
Nodes are discovered through entry points and mounted by the engine operator with
the wengine CLI (which drives uv under the hood). From an engine project:
# Create an engine project if you don't have one yet
wengine init # creates engine.yaml + a pyproject.toml to install into
# Mount every node this package exposes
wengine install aceteam-nodes
# ...or mount only specific nodes
wengine install aceteam-nodes --only LLM --only APICall
wengine install runs uv add aceteam-nodes and records each node in the
operator-controlled name map (engine.yaml). It reads the entry-point table from
package metadata — listed below — without importing the modules. Nodes whose
entry declares an extra (e.g. LLM [llm]) pull that optional dependency
automatically, so wengine install aceteam-nodes --only LLM installs
aceteam-nodes[llm].
Workflows then reference these nodes by their type discriminator (LLM,
APICall, …). See the engine's node-distribution docs
for the full install/uninstall surface and the trust model.
To add the package (and its optional deps) to an environment directly:
pip install aceteam-nodes # core nodes only
pip install "aceteam-nodes[llm]" # + LLM (aceteam-aep)
pip install "aceteam-nodes[browser-fetch]" # + BrowserFetch (Playwright)
pip install "aceteam-nodes[xpath-extract]" # + XPathExtract (lxml)
uvuv add aceteam-nodes # core nodes only
uv add "aceteam-nodes[llm]" # + LLM (aceteam-aep)
uv add "aceteam-nodes[browser-fetch]" # + BrowserFetch (Playwright)
uv add "aceteam-nodes[xpath-extract]" # + XPathExtract (lxml)
| Node | Extra | Description |
|---|---|---|
| LLM | llm | AI text generation via aceteam-aep (OpenAI, Anthropic, Google, xAI, Ollama) |
| APICall | — | HTTP requests with Jinja templating |
| Shell | — | Run shell commands and capture stdout/stderr (trusted engines only) |
| BrowserFetch | browser-fetch | Authenticated web fetch via Playwright |
| DiscordBotInfo | discord-bot-info | Return the authenticated Discord bot's ID and username |
| DiscordListChannels | discord-list-channels | List channels in a Discord server |
| DiscordReadMessages | discord-read-messages | Fetch recent messages from a channel (Message Content intent required) |
| DiscordSendMessage | discord-send | Send a message to a Discord channel |
| SlackListChannels | slack-list-channels | List workspace channels via conversations.list |
| SlackReadMessages | slack-read-messages | Fetch channel history via conversations.history |
| SlackSearchMessages | slack-search-messages | Search workspace messages (requires SLACK_USER_TOKEN) |
| SlackSendMessage | slack-send | Send a message via Slack Web API |
| TelegramBotInfo | telegram-bot-info | Return the authenticated Telegram bot's ID and username |
| TelegramListChats | telegram-list-chats | Look up metadata for a single chat via getChat |
| TelegramReadMessages | telegram-read-messages | Fetch recent updates via getUpdates (incompatible with webhooks) |
| TelegramSendMessage | telegram-send | Send a message via Telegram Bot API |
| XPathExtract | xpath-extract | XPath extraction over HTML/XML |
Each node needing a heavy/optional dependency has one extra named after the
node (llm, browser-fetch, xpath-extract), so aceteam-nodes[browser-fetch]
reads as "BrowserFetch is installed." The APICall node needs no extra.
BrowserFetch drives a real Chromium profile so it can fetch authenticated pages.
After installing the browser-fetch extra and Playwright's browser binaries,
create the profile interactively:
# After: pip install "aceteam-nodes[browser-fetch]" && playwright install chromium
ace-browser-setup
# equivalent: uv run python scripts/browser_setup.py
LLM provider credentials are read from the environment:
export OPENAI_API_KEY=sk-...
# or
export ANTHROPIC_API_KEY=sk-ant-...
export DISCORD_BOT_TOKEN=... # Discord send/read nodes
export SLACK_BOT_TOKEN=... # Slack send/read/list nodes
export SLACK_USER_TOKEN=... # Slack search node (user token, xoxp-...)
export TELEGRAM_BOT_TOKEN=... # Telegram send/read nodes
# Setup (installs project + dev deps: pyright, pytest, ruff, aceteam-aep, playwright, lxml)
uv sync
# Test
uv run pytest
uv run pytest -x # stop on first failure
# Lint & format
uv run ruff check && uv run ruff format
# Type check
uv run pyright
# Build
uv build
# Release
scripts/release.sh -v vX.Y.Z --dry-run # preview
scripts/release.sh -v vX.Y.Z -y # publish to PyPI + GitHub
Add three things in lockstep:
src/aceteam_nodes/nodes/ (with its TYPE_INFO).nodes/__init__.py.__init__.py.[project.entry-points."aceteam_workflow_engine.nodes"] in pyproject.toml (append [extra_dependency_name] if it needs an optional dependency).MIT
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
aceteam-workflow-engineEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aceteam-workflow-engine>=2.0.0rc14 | runtime |
httpxEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | httpx>=0.28.0 | runtime |
jinja2Environment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | jinja2>=3.1.0 | runtime |
overridesEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | overrides>=7.7.0 | runtime |
platformdirsEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | platformdirs>=4.0.0 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pydantic>=2.11.0 | runtime |
pyyamlEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pyyaml>=6.0 | runtime |
playwright-stealthEnvironment{
"extras": "",
"marker": "extra == \"browser-fetch\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | playwright-stealth>=2.0.3; extra == "browser-fetch" | runtime |
playwrightEnvironment{
"extras": "",
"marker": "extra == \"browser-fetch\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | playwright>=1.47.0; extra == "browser-fetch" | runtime |
discord-pyEnvironment{
"extras": "",
"marker": "extra == \"discord-bot-info\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | discord-py>=2.4.0; extra == "discord-bot-info" | runtime |
discord-pyEnvironment{
"extras": "",
"marker": "extra == \"discord-list-channels\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | discord-py>=2.4.0; extra == "discord-list-channels" | runtime |
discord-pyEnvironment{
"extras": "",
"marker": "extra == \"discord-read-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | discord-py>=2.4.0; extra == "discord-read-messages" | runtime |
discord-pyEnvironment{
"extras": "",
"marker": "extra == \"discord-send\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | discord-py>=2.4.0; extra == "discord-send" | runtime |
insightfaceEnvironment{
"extras": "",
"marker": "extra == \"face-blur\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | insightface>=0.7.3; extra == "face-blur" | runtime |
numpyEnvironment{
"extras": "",
"marker": "extra == \"face-blur\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | numpy>=1.26.0; extra == "face-blur" | runtime |
onnxruntimeEnvironment{
"extras": "",
"marker": "extra == \"face-blur\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | onnxruntime>=1.17.0; extra == "face-blur" | runtime |
pillowEnvironment{
"extras": "",
"marker": "extra == \"face-blur\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | pillow>=10.0.0; extra == "face-blur" | runtime |
aceteam-aepEnvironment{
"extras": "",
"marker": "extra == \"llm\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aceteam-aep>=0.2.0; extra == "llm" | runtime |
aiohttpEnvironment{
"extras": "",
"marker": "extra == \"slack-list-channels\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aiohttp>=3.14.1; extra == "slack-list-channels" | runtime |
slack-sdkEnvironment{
"extras": "",
"marker": "extra == \"slack-list-channels\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | slack-sdk>=3.42.0; extra == "slack-list-channels" | runtime |
aiohttpEnvironment{
"extras": "",
"marker": "extra == \"slack-read-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aiohttp>=3.14.1; extra == "slack-read-messages" | runtime |
slack-sdkEnvironment{
"extras": "",
"marker": "extra == \"slack-read-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | slack-sdk>=3.42.0; extra == "slack-read-messages" | runtime |
aiohttpEnvironment{
"extras": "",
"marker": "extra == \"slack-search-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aiohttp>=3.14.1; extra == "slack-search-messages" | runtime |
slack-sdkEnvironment{
"extras": "",
"marker": "extra == \"slack-search-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | slack-sdk>=3.42.0; extra == "slack-search-messages" | runtime |
aiohttpEnvironment{
"extras": "",
"marker": "extra == \"slack-send\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | aiohttp>=3.14.1; extra == "slack-send" | runtime |
slack-sdkEnvironment{
"extras": "",
"marker": "extra == \"slack-send\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | slack-sdk>=3.42.0; extra == "slack-send" | runtime |
python-telegram-botEnvironment{
"extras": "",
"marker": "extra == \"telegram-bot-info\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | python-telegram-bot>=21.0; extra == "telegram-bot-info" | runtime |
python-telegram-botEnvironment{
"extras": "",
"marker": "extra == \"telegram-list-chats\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | python-telegram-bot>=21.0; extra == "telegram-list-chats" | runtime |
python-telegram-botEnvironment{
"extras": "",
"marker": "extra == \"telegram-read-messages\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | python-telegram-bot>=21.0; extra == "telegram-read-messages" | runtime |
python-telegram-botEnvironment{
"extras": "",
"marker": "extra == \"telegram-send\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | python-telegram-bot>=21.0; extra == "telegram-send" | runtime |
lxmlEnvironment{
"extras": "",
"marker": "extra == \"xpath-extract\"",
"requires_python": ">=3.12",
"evaluation": "NOT_EVALUATED"
} | lxml>=6.1.0; extra == "xpath-extract" | runtime |
bdist_wheel · 51.42 KB · Python py3
sdist · 186.95 KB · Python source
Observed since 20 Oct, 18:10 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:da3fdaeda2f3c85ee8e0e8cf41a288dd71ee9443daba96883b45ad33c96a1e50