skills/a6-plugin-ext-plugin/SKILL.md
Skill for configuring the Apache APISIX external plugin system (ext-plugin-pre-req, ext-plugin-post-req, ext-plugin-post-resp) via the a6 CLI. Covers Plugin Runner architecture, configuration for Go/Java/Python runners, RPC protocol, graceful degradation, and performance considerations.
npx skillsauth add moonming/a6 a6-plugin-ext-pluginInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
The APISIX external plugin system lets you run plugins written in Go, Java, Python, or JavaScript via a Plugin Runner process. APISIX communicates with the runner over a Unix socket using FlatBuffers serialization.
Three plugins control when external plugins execute:
| Plugin | Phase | Priority | Description |
|--------|-------|----------|-------------|
| ext-plugin-pre-req | rewrite | 12000 | Before built-in Lua plugins |
| ext-plugin-post-req | access | −3000 | After Lua plugins, before upstream |
| ext-plugin-post-resp | before_proxy | −4000 | After upstream response received |
All three plugins share the same schema:
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| conf | array | No | — | List of external plugins to execute |
| conf[].name | string | Yes | — | Plugin identifier (1–128 chars) |
| conf[].value | string | Yes | — | JSON string configuration passed to the plugin |
| allow_degradation | boolean | No | false | When true, requests continue if runner is unavailable |
┌──────────┐ Unix Socket ┌───────────────┐
│ APISIX │ ◄──────────────► │ Plugin Runner │
│ (Nginx) │ FlatBuffers │ (Go/Java/Py) │
└──────────┘ └───────────────┘
ext-plugin-* trigger, APISIX sends an RPC over Unix socket| Language | Repository | Status |
|----------|------------|--------|
| Go | apache/apisix-go-plugin-runner | GA |
| Java | apache/apisix-java-plugin-runner | GA |
| Python | apache/apisix-python-plugin-runner | Experimental |
| JavaScript | zenozeng/apisix-javascript-plugin-runner | Community |
APISIX manages the runner as a subprocess:
ext-plugin:
cmd: ["/path/to/runner-executable", "run"]
# Go runner
ext-plugin:
cmd: ["/opt/apisix-go-runner", "run"]
# Java runner
ext-plugin:
cmd: ["java", "-jar", "-Xmx1g", "-Xms1g", "/opt/apisix-runner.jar"]
# Python runner
ext-plugin:
cmd: ["python3", "/opt/apisix-python-runner/apisix/main.py", "start"]
For local development, run the runner separately:
# APISIX config.yaml — do NOT set cmd
ext-plugin:
path_for_test: "/tmp/runner.sock"
# Start runner manually
APISIX_LISTEN_ADDRESS=unix:/tmp/runner.sock ./runner run
Pass environment variables to the runner:
nginx_config:
envs:
- MY_ENV_VAR
- DATABASE_URL
a6 route create -f - <<'EOF'
{
"id": "ext-auth",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"}
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "ext-chain",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [
{"name": "AuthFilter", "value": "{\"token_required\":true}"},
{"name": "RateLimiter", "value": "{\"requests_per_second\":100}"}
],
"allow_degradation": true
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
a6 route create -f - <<'EOF'
{
"id": "full-ext",
"uri": "/api/*",
"plugins": {
"ext-plugin-pre-req": {
"conf": [{"name": "auth-check", "value": "{}"}]
},
"ext-plugin-post-req": {
"conf": [{"name": "request-transform", "value": "{}"}]
},
"ext-plugin-post-resp": {
"conf": [{"name": "response-logger", "value": "{}"}]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {"backend:8080": 1}
}
}
EOF
Execution order: pre-req → (Lua plugins) → post-req → (upstream) → post-resp
version: "1"
routes:
- id: ext-plugin-demo
uri: /api/*
plugins:
ext-plugin-pre-req:
conf:
- name: AuthFilter
value: '{"token_required":true}'
allow_degradation: true
upstream_id: my-upstream
| Feature | ext-plugin-pre-req | ext-plugin-post-req | ext-plugin-post-resp | |---------|-------------------|---------------------|---------------------| | Phase | rewrite | access | before_proxy | | Runs | Before Lua plugins | After Lua plugins | After upstream response | | proxy-mirror | ✅ | ✅ | ❌ | | proxy-cache | ✅ | ✅ | ❌ | | proxy-control | ✅ | ✅ | ❌ | | mTLS to upstream | ✅ | ✅ | ❌ |
ext-plugin-post-resp limitation: Uses lua-resty-http internally,
which makes it incompatible with proxy-mirror, proxy-cache,
proxy-control, and mTLS to upstream.
allow_degradation: true for non-critical plugins| Symptom | Cause | Fix |
|---------|-------|-----|
| failed to receive RPC_PREPARE_CONF | Runner not listening or socket path mismatch | Verify path_for_test matches APISIX_LISTEN_ADDRESS |
| 503 Service Unavailable | Runner crashed or not started | Check runner logs; verify cmd path is correct |
| Runner not receiving env vars | Nginx hides env vars by default | Add vars to nginx_config.envs in config.yaml |
| Slow response times | External plugin doing heavy work | Profile runner; consider async processing |
| ext-plugin-post-resp conflicts | Incompatible with proxy-* plugins | Use ext-plugin-post-req instead, or remove proxy-mirror/cache |
tools
Core skill for working with the a6 CLI — the Apache APISIX command-line tool. Provides project conventions, command patterns, architecture overview, and development workflow. Load this skill when working on a6 source code, adding new commands, writing tests, or modifying any a6 component.
tools
Recipe skill for implementing multi-tenant API gateway patterns using the a6 CLI. Covers tenant isolation via Consumer Groups, host/path/header-based routing, per-tenant rate limiting, context forwarding with proxy-rewrite, and declarative config sync workflows for multi-tenant management.
tools
Recipe skill for configuring mutual TLS (mTLS) using the a6 CLI. Covers SSL certificate management, upstream mTLS to backend services, client certificate verification, and end-to-end mTLS setup from client through APISIX to upstream.
tools
Recipe skill for configuring upstream health checks using the a6 CLI. Covers active health checks (HTTP probing), passive health checks (response analysis), combining both, configuring healthy/unhealthy thresholds, and monitoring upstream node status.