Sends a single CEF event via @cef-ai/vault-sdk.
- Builds a
VaultSDKfrom the action's wallet URI + vault base URL. - Resolves the wallet's vault (
sdk.vault.current()). The wallet must already be onboarded — onboarding is out of scope for this action. - Publishes one event to
vault.scope(<scope>).publish(...). - Exits non-zero if vault-api rejects the event.
The action does not call vault.agents.connect(...). We assume the
receiving agent has been connected to the wallet's vault in advance.
- uses: your-org/Cef-Send-Event-Action@v2
with:
wallet_json: ${{ secrets.CEF_WALLET_JSON }}
wallet_password: ${{ secrets.CEF_WALLET_PASSWORD }}
vault_base_url: ${{ secrets.CEF_VAULT_BASE_URL }}
event_type: "MY_CUSTOM_EVENT"
event_payload: ${{ toJSON(github.event) }}Build the payload in a step using jq and GITHUB_EVENT_PATH, then pass
it to the action.
jobs:
send-pr-event:
runs-on: ubuntu-latest
steps:
- id: payload
env:
NOTION_API_KEY: ${{ secrets.NOTION_API_KEY }}
run: |
jq -s '.[0] + {notion_api_key: env.NOTION_API_KEY}' "$GITHUB_EVENT_PATH" > payload.json
echo "payload<<EOF" >> $GITHUB_OUTPUT
cat payload.json >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- uses: your-org/Cef-Send-Event-Action@v2
with:
wallet_json: ${{ secrets.CEF_WALLET_JSON }}
wallet_password: ${{ secrets.CEF_WALLET_PASSWORD }}
vault_base_url: ${{ secrets.CEF_VAULT_BASE_URL }}
scope: "default"
context: "pr-events"
event_type: "GITHUB_ACTION_PR_EVENT"
event_payload: ${{ steps.payload.outputs.payload }}| Input | Required | Default | Description |
|---|---|---|---|
wallet_json |
yes | — | Cere/Polkadot JSON keystore (the full JSON, as a string). |
wallet_password |
yes | — | Passphrase that decrypts the keystore. |
vault_base_url |
yes | — | Vault API base URL. |
gar_url |
no | https://gar.compute.test.ddcdragon.com |
Global Agent Registry endpoint. |
marketplace_endpoint |
no | "" (vault-sdk default) |
Marketplace API endpoint forwarded to VaultSDK. |
event_type |
yes | — | CEF event type identifier. |
event_payload |
no | "{}" |
JSON string for the event body. |
scope |
no | "default" |
Vault scope (namespace) to publish into. |
context |
no | derived from GITHUB_REPOSITORY@GITHUB_REF |
Scope context (per-thread id). |
gemini_api_key |
no | "" |
Injected into payload as gemini_api_key. |
In the consuming repo, Settings → Secrets and variables → Actions:
| Secret | Required by | Description |
|---|---|---|
CEF_WALLET_JSON |
always | Cere/Polkadot JSON keystore (paste the file contents). |
CEF_WALLET_PASSWORD |
always | Passphrase for the keystore. |
CEF_VAULT_BASE_URL |
always (unless hardcoded per env) | Vault API base URL. |
CEF_GEMINI_API_KEY |
optional | Enables the agent's Gemini analysis. |
CEF_NOTION_API_KEY |
optional | Enables the agent's Notion execution-log append. |
CEF_NOTION_PAGE_ID |
optional | Target Notion page; falls back to the agent's route table / settings. |
secrets.GITHUB_TOKEN is auto-issued per run — you don't add it manually.
Add any other secrets your payload needs and inject them when building
event_payload in a prior step.
.github/workflows/send-event.yml runs this repository's action against
itself, against either the dev or stage CEF cluster. It does not
trigger on push — running on every push would spam the cluster. Trigger
it from the Actions tab:
- Go to Actions → Send github_event → Run workflow.
- Pick the target cluster (
devorstage). - Run.
Cluster URLs are baked into the workflow:
| Env | Vault | GAR | Marketplace |
|---|---|---|---|
dev |
https://vault-api.compute.dev.ddcdragon.com |
https://gar.compute.dev.ddcdragon.com |
https://agent-marketplace.compute.dev.ddcdragon.com |
stage |
https://vault-api.compute.test.ddcdragon.com |
https://gar.compute.test.ddcdragon.com |
https://agent-marketplace.compute.test.ddcdragon.com |
The workflow:
- Picks the cluster URLs based on the
environmentinput. - Reads the real GitHub event from
$GITHUB_EVENT_PATH(aworkflow_dispatchevent when triggered manually). - Merges in optional pipeline activators from secrets
(
GITHUB_TOKEN,CEF_GEMINI_API_KEY,CEF_NOTION_API_KEY,CEF_NOTION_PAGE_ID). Keys whose secret isn't set are dropped, so the agent never receives empty strings. - Publishes the assembled payload via this action (
uses: ./).
Required secrets in this repo for the workflow to succeed:
CEF_WALLET_JSON, CEF_WALLET_PASSWORD. The rest are optional and
just unlock more of the agent pipeline downstream.
The action sends whatever you pass in event_payload (parsed as JSON).
Before publishing it adds:
delivery_id—${GITHUB_RUN_ID}-${Date.now()}if not present.timestamp— current ISO time if not present.gemini_api_key— set ifgemini_api_keyinput is non-empty.
test.js is a local runner. It builds a synthetic payload and uses the
same publish path the action uses. For convenience it loads a Cere/Polkadot
JSON keystore from a hardcoded local path and uses a hardcoded password —
those are dev-only; production runs go through the action's
wallet_json / wallet_password inputs (sourced from GH secrets).
Create .env (gitignored) in the project root with the cluster URLs:
VAULT_BASE_URL=https://vault.compute.dev.ddcdragon.com
GAR_URL=https://gar.compute.dev.ddcdragon.com
# EVENT_TYPE defaults to "github_event" in test.js if unset
SCOPE=default
# CONTEXT=optional-override
# E2E pipeline activators (all optional secrets — without them the
# corresponding agent step gets skipped, but the event still publishes):
# GH_TOKEN=ghp_... # enables enrichGithub → real diffs/commits/tree
# GEMINI_API_KEY=... # enables Gemini analysis (otherwise heuristic)
# NOTION_API_KEY=secret_ # enables runNotionFlow execution-log append
# NOTION_PAGE_ID=... # destination page; defaults to a baked dev page
# COMPARE_BASE=origin/main # diff range base — leave default to compare
# # against main (gives Gemini the whole branch
# # diff, not just HEAD~1..HEAD). Override for
# # narrower ranges.
# COMPARE_BEFORE=<sha> # alternative: pin a specific `before` shatest.js needs a GitHub PAT so the agent's enrichGithub can fetch
real diffs via api.github.com/repos/<repo>/compare/<before>...<after>.
Use a fine-grained PAT scoped to read-only:
-
Resource owner → your user (or the org owning the repo).
-
Repository access → select the repo(s) you'll test against.
-
Permissions → Repository → Contents: Read-only.
-
Generate, copy the
github_pat_…value, paste into.env:GH_TOKEN=github_pat_…
In the GitHub Actions workflow you do not need this — the workflow
uses the auto-issued secrets.GITHUB_TOKEN per run.
The agent's Gemini prompt has an explicit skip-check: it returns
SHOULD_LOG: no when it sees "No file data available." or only
trivial commits. To clear that bar in a test run you need:
- Set
GH_TOKEN— without it, the agent'senrichGithubreturns empty arrays and Gemini sees no diff. - Push the branch first — the agent calls
https://api.github.com/repos/<repo>/compare/<before>...<after>. Both SHAs must exist on the remote, or GitHub 404s and the agent falls back to empty (silently).test.jswarns on startup if HEAD isn't onorigin/<branch>. - Keep
COMPARE_BASE=origin/main(the default) — this widens the compare range to the whole feature-branch diff. A single-commitHEAD~1..HEADrange often looks trivial to Gemini.
Confirm in the agent logs:
step:enrich done {"has_github_token":true,"files":<N>,"commits":<M>,...}
step:analyze done {"should_write":true,"change_type":"feature",...}
step:notion done {"notion_logged":true}
Adjust the TEST_WALLET_PATH / TEST_WALLET_PASSWORD constants at the top
of test.js to point at your local keystore, then:
npm install
node --env-file=.env test.js
# or override the event type:
node --env-file=.env test.js my.custom.eventThe script prints the published eventId on success. Useful for verifying
that a feature branch can talk to the dev cluster before bumping the
action version in workflows.
- Node.js 24 (set up by the action).
- A wallet that has been onboarded into the target vault environment.
- An agent connected to the wallet's vault for the receiving end.
docs/vault-sdk-migration.md— design notes on the migration from@cef-ai/client-sdk.