* feat(api): support global API key from config.yaml (api.global_api_key) Accept a config-defined global API key anywhere a web-UI key is accepted (X-API-Key / Bearer), with no login session and no DB record. Useful for automated deployments and AI agents (HTTP API + MCP). Defaults to empty (disabled); does not require the lbk_ prefix. - templates/config.yaml: add api.global_api_key with security notes - service/apikey.py: verify_api_key checks global key first (constant-time) - docs/API_KEY_AUTH.md: document the global key + security guidance - tests: cover global-key match, prefix-free, fallback-to-db, disabled * feat(mcp): expose LangBot management as an MCP server at /mcp Add an MCP (Model Context Protocol) server so external AI agents can manage a LangBot instance. Reuses the same API-key auth as the HTTP API (including the config.yaml global API key). - pkg/api/mcp/server.py: FastMCP server wrapping the service layer; 21 curated tools across system/bots/pipelines/models/knowledge/mcp-servers/skills - pkg/api/mcp/mount.py: ASGI dispatcher fronting Quart; authenticates /mcp requests with an API key, runs the streamable-HTTP session manager lifespan - controller/main.py: serve the wrapped ASGI app via hypercorn (was run_task) - web: new 'MCP' tab in the API integration dialog showing endpoint, auth, and client config; i18n for 8 locales - tests/manual/mcp_smoke.py: e2e check (401 unauth, list tools, call tools) Tool surface is intentionally curated (not all ~25 route groups) to keep the agent surface small, safe, and maintainable. Extend deliberately. * feat(skills): add in-repo skills/ as the single source of truth Migrate the agent skills + QA/e2e test harness from the (now archived) langbot-app/langbot-skills repo into LangBot/skills/, and add four new skills. Migrated: - langbot-plugin-dev, langbot-testing (e2e), langbot-env-setup, langbot-skills-maintenance, langbot-eba-adapter-dev - the bin/lbs CLI (src/, test/, scripts/, schemas/, qa-agent-docs/) New: - langbot-dev core backend + web development - langbot-deploy Docker/K8s deployment + config.yaml + global API key - langbot-mcp-ops operating the LangBot MCP server (/mcp) - langbot-space-ops operating the Space marketplace MCP server - src/cli.ts repoRoot(): recognize the skills assets root (skills.index.json + bin/lbs) so the CLI works when nested inside the LangBot repo - README.md: unified skill catalog; skills.index.json regenerated Parity with source verified: bin/lbs validate + node test suite match the source repo (only the uncommitted .lbpkg build-artifact fixture differs). * docs(agents): document agent-facing surfaces + API/MCP/skills sync rule * docs(readme): add 'Built for AI Agents' section across all locales Highlight MCP server, in-repo skills (single source of truth), AGENTS.md sync rule, and llms.txt. Cross-link LangBot Space MCP marketplace. * style(mcp): fix ruff format + prettier lint in MCP server and API panel * style(web): prettier format MCP i18n locale entries * docs(skills): note MCP instance control in dev/testing skills All development-guidance skills now point to the LangBot instance MCP server (/mcp) and the Space marketplace MCP server, reusing API keys.
5.4 KiB
Sandbox Skill Authoring
Goal
Verify that Local Agent can use sandbox tools to create, register, activate, and use a LangBot skill package through the same path a user would exercise in Debug Chat.
This flow applies to Docker, nsjail, and E2B backends. API calls are useful diagnostics, but the primary pass/fail signal is the model-driven Debug Chat tool sequence.
Preconditions
- Read
../.envand useLANGBOT_FRONTEND_URLandLANGBOT_BACKEND_URL. - Start LangBot with the intended backend:
BOX_BACKEND=e2bwhen validating E2B.BOX_BACKEND=nsjailwhen validating nsjail.BOX_BACKEND=localordockerwhen validating local container fallback.
- Confirm
/api/v1/box/statusreportsavailable: trueand the expected backend name. - Confirm Debug Chat uses a model with function-calling ability.
- Confirm backend logs say native sandbox tools are available.
Do not store sandbox provider keys, JWTs, OAuth tokens, or localStorage values in the case or notes.
Debug Chat Prompt Pattern
Use a unique skill name per run, for example:
lb-sandbox-agent-e2e-<timestamp>
Send a prompt that requires the model to do all of the following:
-
Use
execto create a multi-file skill under/workspace/<skill-name>. -
Include at least:
SKILL.mdscripts/use.pydata/input.json
-
In the same first
exec, run the script and verify a deterministic marker such as:SANDBOX_COMPLEX_SKILL_OK sum=10 product=24 -
Call
register_skillwithpath=/workspace/<skill-name>. -
Call
activatewithskill_name=<skill-name>. -
Call
execwithworkdir=/workspace/.skills/<skill-name>and run:python3 scripts/use.py && echo SANDBOX_ACTIVATED_WRITEBACK_OK > activated_writeback.txt && cat activated_writeback.txt -
Require the final answer to contain only an explicit success marker:
E2E_OK:<skill-name>
Keep the test script robust to working-directory changes. Prefer resolving data paths from __file__:
from pathlib import Path
data_path = Path(__file__).resolve().parent.parent / "data" / "input.json"
Success Criteria
The UI should show an assistant final response containing E2E_OK:<skill-name>.
Backend logs should show:
exec tool invokedregister_skillactivate- a second
execwhose workdir is/workspace/.skills/<skill-name> backend=e2b,backend=nsjail, or the expected local backend
After the run, verify the skill store through the UI or API:
- Skill root lists
SKILL.md,scripts,data, andactivated_writeback.txt. scripts/use.pyis readable.data/input.jsonis readable.activated_writeback.txtcontainsSANDBOX_ACTIVATED_WRITEBACK_OK./api/v1/box/errorsis empty.
Existing Skill Edit Variant
The base sandbox-skill-authoring-e2e case only proves create, register,
activate, and use. To prove that an already activated skill can be modified,
run sandbox-skill-authoring-edit-existing-e2e or use its prompt pattern.
The edit variant must include these additional checks:
-
The second
execusesworkdir=/workspace/.skills/<skill-name>. -
The second
execoverwritesSKILL.md,data/input.json, andscripts/use.pyunder the activated skill path. -
The modified script prints a deterministic marker such as:
SANDBOX_SKILL_MODIFIED_OK sum=11 product=56 marker=<updated-marker> -
grep -q <updated-marker> SKILL.md scripts/use.py data/input.jsonsucceeds in the same activated-path command. -
Filesystem evidence under the Box-managed skill store shows the updated marker, not only the original create marker.
If the model stops after activation and only reruns the original script, treat that run as a failed edit-existing E2E even when create/register/activate succeeded.
Diagnostic Checks
Use these only after the model-driven Debug Chat flow fails:
/api/v1/box/statusto confirm backend selection and recent errors./api/v1/box/sessionsto check leaked or conflicting sessions.- Direct backend probes to separate provider credentials from LangBot integration.
- Filesystem inspection under the configured Box-managed skill store.
For E2B raw HTTP diagnostics, include a valid template id such as base; a missing template can produce schema validation errors that are unrelated to authentication.
Known Pitfalls
- When Box is available, skills may be owned by the Box runtime and stored in Box-managed skill storage. Do not assume
data/skillsis the active source of truth. - Public E2B does not provide local bind mounts. Main workspace and activated skill extra mounts must be synchronized into and back out of the E2B sandbox.
- Session metadata should keep LangBot logical paths such as
/workspace; storing provider-internal paths can make later requests look incompatible. - nsjail versions differ. Some expose only
--disable_clone_new*flags and use--bindmountinstead of--rw_bind. - On WSL, cgroup v2 may exist but not be writable. The backend should warn and fall back to rlimits rather than fail the sandbox.
- If
ALL_PROXYuses a SOCKS URL andsocksiois not installed, some Python HTTP clients can fail during startup. Prefer consistent HTTP proxy variables unless SOCKS support is installed.
Related Troubleshooting
sandbox-native-tools-unavailablee2b-extra-mount-sync-missingbox-session-conflict-logical-metadatansjail-cli-compatibilitysocks-proxy-without-socksio