Install
$ agentstack add skill-xaiht-tlamatini-setup-new-acpx-key Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Dangerous shell/eval execution.
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Set Up a New ACPX Agent Key
Configures the credential for ONE ACPX agent_id so acp_spawn(agent_id=...) launches the child CLI authenticated. The runtime never asks the LLM for a key: each child reads its canonical env var, injected via subprocess.Popen(env={**os.environ, **spec.env}) in agent/acpx/runtime.py::AcpSession.spawn_child() (and _oneshot_send_turn).
Canonical env-var map
| agent_id | Env var the CLI reads | Top-level config.json key? | |------------|-----------------------|----------------------------| | claude | ANTHROPIC_API_KEY | YES — also read by imaging/image_interpreter.py + opus_client/claude_opus_client.py. | | gemini | GEMINI_API_KEY (+ GOOGLE_API_KEY alias) | YES — see _section_gemini in config.json. | | codex | OPENAI_API_KEY | NO. | | qwen | DASHSCOPE_API_KEY | NO. | | cursor | none (uses own login) | NO. | | copilot | none (gh auth login)| NO. | | pi, droid, iflow, kilocode, kimi, kiro, opencode | per upstream — check each CLI's docs | NO. | | tlamatini| n/a (self-host) | NO. |
If unsure: agent/acpx/agent_registry.py::DEFAULT_ACP_AGENTS.
Procedure
1. Verify the CLI is resolvable
The runtime calls windows_spawn.resolve_command(spec.command) at spawn time and surfaces AGENT_NOT_FOUND if it cannot find the binary.
where ${cli_command} # Windows
which ${cli_command} # POSIX
If absent: install the CLI per its upstream docs, or pass command_override and add it to the agent block in step 3.
2. Add the secret to data.keys (gitignored vault)
Open data.keys at the repo root and add — or update — a line KEY=VALUE. Use the canonical name from the table:
ANTHROPIC_API_KEY=sk-ant-api03-... # claude
GEMINI_API_KEY=AIzaSy... # gemini
GOOGLE_API_KEY=AIzaSy... # gemini alias (keep in sync)
OPENAI_API_KEY=sk-proj-... # codex
DASHSCOPE_API_KEY=sk-... # qwen
data.keys is in .gitignore (line 265). Never commit it.
3. Update Tlamatini/agent/config.json
Two layers, applied based on the table above:
Layer A — top-level key (claude / gemini only):
{
"ANTHROPIC_API_KEY": "",
"GEMINI_API_KEY": ""
}
Layer B — per-agent env injection (every agent_id that needs a key):
{
"acpx": {
"agents": {
"${agent_id}": {
"command": "",
"env": { "": "" }
}
}
}
}
Real worked examples (mirror these exactly):
"claude": {
"command": "C:/Users//AppData/Roaming/npm/claude.cmd",
"env": { "ANTHROPIC_API_KEY": "sk-ant-api03-..." }
},
"gemini": {
"command": "C:/Users//AppData/Roaming/npm/gemini.cmd",
"env": {
"GEMINI_API_KEY": "AIzaSy...",
"GOOGLE_API_KEY": "AIzaSy..."
}
},
"codex": { "command": "codex", "env": { "OPENAI_API_KEY": "sk-proj-..." } },
"qwen": { "command": "qwen-code", "env": { "DASHSCOPE_API_KEY": "sk-..." } }
How the merge resolves at spawn (read once, never wonder again):
agent/acpx/config.py::_coerce_agents_env()plucks eachenvdict
out of acpx.agents. into AcpxConfig.agents_env.
agent/acpx/agent_registry.py::build_agent_registry()merges that
dict on top of DEFAULT_ACP_AGENTS[].env (override wins).
AcpSession.spawn_child()builds the child env as
{**os.environ, **self.spec.env} — explicit acpx.agents..env wins over an exported shell variable.
4. Wire regen_secrets.py (only when introducing a brand-new key)
regen_secrets.py is the toggle between "push-able" placeholders and real "keyed" values. If you added a data.keys entry that the script does not already handle, extend it.
Patch patch_config_json() in regen_secrets.py (around lines 128-134):
# Top-level (claude / gemini only — skip for everything else)
set_top("", "")
# Per-agent env injection — required for every agent that needs a key
set_acpx_env("", "", "")
Also list the new key in the docstring at the top of regen_secrets.py (lines 12-16) so the file's own self-documentation stays accurate.
Existing wired keys (do NOT duplicate):
ANTHROPIC_API_KEY— top +acpx.agents.claude.envGEMINI_API_KEY,GOOGLE_API_KEY— top (GEMINI only) +acpx.agents.gemini.env(both)OLLAMA_TOKEN— top only
5. Apply the changes
If you edited config.json directly (Layer A + Layer B), you are done.
If you only edited data.keys (and updated regen_secrets.py in step 4 when needed), run the regen script to splat the values into config.json:
python regen_secrets.py --mode keyed --dry-run # preview
python regen_secrets.py --mode keyed # apply
Always verify with git diff Tlamatini/agent/config.json that no unexpected keys flipped to placeholders or vice versa.
6. Restart Django
config.json is read at startup by agent/config_loader.py and the ACPX runtime caches the resolved registry. The new key does NOT take effect until the server restarts. Stop and restart manage.py runserver --noreload (or relaunch Tlamatini.exe).
7. Verify
In the Tlamatini chat with Multi-Turn enabled, ask the LLM to:
- Call
acp_doctorand confirm the row for${agent_id}shows
resolvable: true.
- Call
acp_spawn(agent_id="${agent_id}", task="...")and confirm the
spawn returns a session_id (no AGENT_NOT_FOUND).
- Call `acpsendandwait(sessionid, "Reply with the literal token
ALIVE."). The transcript at /.transcript.ndjson` must contain a non-empty assistant turn — proves the key was injected and the CLI authenticated. Empty transcript = key not reaching the child.
- Call
acp_kill(session_id).
Or run the seeded GEMINI LIVE REASONING SHOWCASE prompt (idPrompt 31 from migration 0073_acpx_demo_gemini_uplift.py) for an end-to-end reasoning round-trip when agent_id=gemini.
Common pitfalls
- Top-level vs per-agent: the top-level
ANTHROPIC_API_KEY/
GEMINI_API_KEY is read by Tlamatini's own internal callers (image_interpreter.py, opus_client.py); the per-agent acpx.agents..env is read by the spawned child. Setting only ONE half breaks the other half. For claude/gemini, set BOTH.
- Forgetting the alias: Gemini CLI versions vary; some only read
GEMINI_API_KEY, others only GOOGLE_API_KEY. Always inject BOTH under acpx.agents.gemini.env to avoid the fragility.
- Empty
envdict survives merge:_coerce_agents_env()skips
entries where env is missing or empty, so the dict shape "agents": { "claude": {} } does NOT inject anything. Make sure the env key actually contains the env vars.
- Stale process env: if you exported the key in your shell BEFORE
starting Django and now want config.json to win, remember the merge order: explicit acpx.agents..env always wins over os.environ.
- CLI not on PATH: symptom is
AGENT_NOT_FOUNDfromacp_doctor,
not an auth error. Fix the command field, not the env field.
- Pushing keys: before
git push, run
python regen_secrets.py --mode push-able, push, then python regen_secrets.py --mode keyed to restore. Never commit real values into config.json.
Output
{
"files_changed": [
"data.keys",
"Tlamatini/agent/config.json",
"regen_secrets.py"
],
"doctor_ok": true
}
regen_secrets.py is included only when step 4 added a brand-new set_top / set_acpx_env rule.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: XAIHT
- Source: XAIHT/Tlamatini
- License: MIT
- Homepage: https://xaiht.org
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.