Skip to content

Maestro v0.1.2 — your data, your APIs

Choose a tag to compare

@Yigtwxx Yigtwxx released this 28 Jul 11:39
· 83 commits to main since this release

A feature release. Agents can now read your own uploaded documents and conversation memory, call HTTP endpoints you register yourself, and hand each other tools mid-run. The agent creation flow was rebuilt, and the documentation moved to its own site.

Agents can read your own data

Two new tools, document_search and memory_recall, run over the user's uploaded documents and conversation memory in Qdrant. They are keyless — nothing to configure beyond DOCUMENT_SEARCH_ENABLED / MEMORY_RECALL_ENABLED — and every query is scoped by user_id at the service layer, so one account's documents cannot enter another's context. Both degrade to a "no results" note on a cold Qdrant rather than an error, so they are safe to leave on before anything is ingested. Every domain squad declares them.

The Main Agent can also run a bounded, read-only pass over exactly those two tools before it plans, so the subtask breakdown is grounded in what you actually have rather than guessed at. MAIN_AGENT_DISCOVERY_ENABLED turns it off; MAIN_AGENT_DISCOVERY_MAX_CALLS (default 2) bounds it. No external or action tool can run at the main tier.

Document upload limit is raised to 5 MB, validated client-side before the request.

Register your own APIs as agent tools

An endpoint you register becomes a custom_api__{slug} action a subagent can call. Method, path parameters, query values, static headers and one credential (bearer, header or query), plus a dry-run test call that goes through the real execution path — a check that takes a different route can pass while the real call fails. It lives in the Capabilities step of the agent wizard, so registering an endpoint and attaching it to an agent is one flow.

This is the first place in Maestro where a user supplies the host an outbound request goes to, so none of the "every base URL is a constant of ours" reasoning that covers the GitHub/X/Discord/Maps tools applies. url_guard runs twice — at registration and again on every call, because a record outlives its validation and the DNS for a host you own is yours to change. Redirects are never followed: without a hard-coded host there is nothing to bound the hop to, and following one is how an Authorization header reaches another origin. Path parameters are percent-encoded with an empty safe set. Responses are byte-capped while streaming. The credential is AES-256-GCM in Mongo and is kept out of every response by both a query projection and an explicit public field list. The tool's own name and description pass prompt_guard, because they are interpolated into the subagent's system prompt.

The residual risk is DNS rebinding, which url_guard documents as unclosed — so CUSTOM_API_TOOLS_ENABLED ships false. Turning it on is an operator saying the deployment can accept outbound requests to hosts its users choose.

Tools are assigned per subagent, and can be requested mid-run

The Main Agent can now hand each squad member a subset of the domain's tools rather than the whole set. A member that finds it needs something it was not given emits a request_tool directive; the Main Agent, acting as a gatekeeper, autonomously grants or denies it. No task pause and no human in the loop — this is distinct from the ask_user channel.

A grant can never bypass a gate: the grantable pool resolves through the same domain/switch/credential filter as any other tool, so a subagent cannot obtain something the operator disabled or you hold no key for. Escalations are capped by SUBAGENT_MAX_TOOL_GRANTS (default 2), and a grant raises tool variety, never call volume — the per-tool and total call caps still bound execution. Grant state stays local to each subtask run, so a grant to one member in a parallel wave never leaks to its siblings.

Rebuilt agent creation and registry

The single long agent form is now a five-step wizard — Identity, Behavior, Capabilities, Routing, Preview — with per-step validation. Its rules live in pure, testable logic keyed off shared limits that a backend parity test compares against the Pydantic schema, so the form cannot silently drift from what the API accepts.

The agent list is a searchable registry with distinct cards for built-in and custom agents, and per-domain hover motifs. The tool catalog is served from a live endpoint carrying each tool's capability status, instead of being duplicated in the frontend.

Documentation site

The docs now build with MkDocs Material and publish to GitHub Pages on every change: https://yigtwxx.github.io/Maestro/ — quick start, architecture, a comparison page, configuration, deployment, API reference, security policy and the contributing guide.

Security and defaults

  • CODE_EXECUTION_ENABLED now defaults to false. It is the one tool whose blast radius is the host: enabling it means mounting the Docker socket, which hands agent-authored code the ability to start privileged containers outside the sandbox. The daemon probe in front of it is an availability check, not a security boundary.
  • /health/ready no longer returns its per-dependency checks map to anonymous callers. The probe stays publicly reachable and the 200/503 status code is unchanged, so no uptime monitor needs a credential — but which backing service is down is reconnaissance. A degraded Redis, for instance, announces that rate-limit buckets just fell back to process-local counters. Set HEALTH_DETAIL_TOKEN and send it as X-Health-Token to get the map back; unset (the default) withholds it from everyone.
  • Base images are pinned by digest, and the README carries an OpenSSF Scorecard badge.

CI

Two blocking gates were added for things the existing ones structurally cannot catch:

  • Invariantssemgrep --error over hand-written rules for the architectural invariants no public ruleset knows: unscoped Qdrant queries, a redirect-following HTTP client outside the one tool allowed to follow one, a credential reaching a logger, raw SQL outside Alembic. A second step re-runs the rules against fixtures and asserts the exact per-rule hit count, so a rule that silently stops matching fails the build instead of reporting zero findings and looking clean.
  • Smoke — boots the built backend image against the four compose services, runs alembic upgrade head from inside it, polls /health/ready until Postgres, Mongo, Qdrant and Redis all answer, and asserts a public route responds. pytest runs over an ASGI transport with fixtures in place of real servers, so a missing runtime dependency, a broken migration chain or an import-time settings failure passes every other gate and would otherwise surface first on deploy.

Alembic migrations are also diffed against the models on a real Postgres, and the frontend gained a vitest unit suite wired into CI. Backend coverage is reported in the log and deliberately not gated on a threshold.

Operations

  • MongoDB's dev host port moved from 27017 to 27018. A native MongoDB service (Homebrew's mongodb-community, the Windows service) already owns 27017 on plenty of machines, and it binds 127.0.0.1 specifically while Docker's proxy binds the wildcard — a loopback-specific bind wins, so localhost:27017 silently reached the native server. Those installs default to authorization enabled, which surfaced as an unrelated-looking "Command update requires authentication" from the seed script. If your .env pins MONGODB_URL to port 27017, update it.
  • Qdrant gained a healthcheck, so the backend waits on service_healthy rather than starting against a vector store that cannot answer yet.
  • The remaining uncapped production containers (the one-shots and Caddy) have memory limits. An unbounded container that grows gets resolved by the kernel's OOM killer, which is free to pick a long-running service instead of the offender.

Interface and fixes

  • A status-aware notification bell in the top bar surfaces task outcomes and can be dismissed.
  • Locally available Ollama models are annotated and suggested in the per-role model picker.
  • JetBrains Mono and Space Grotesk are self-hosted instead of fetched from Google Fonts.
  • Trace spans render human-readable labels and formatted timestamps; the architect graph uses compact status icons.
  • The config panel no longer auto-opens on remount when a task is already running.
  • Best-effort RAG failures are logged instead of swallowed silently.
  • Editing a custom API tool from a credential-free auth mode to a credentialed one now requires a secret; a failed tool delete surfaces instead of throwing an unhandled rejection.
  • Muted foreground colour lightened for contrast.

Full changelog: v0.1.1...v0.1.2