Skip to content

Improve agent ergonomics: deployment log tailing, saved-params reuse, and input schema constraints - #12

Merged
chrisghill merged 2 commits into
mainfrom
fine-tuning-20260804
Aug 4, 2026
Merged

Improve agent ergonomics: deployment log tailing, saved-params reuse, and input schema constraints#12
chrisghill merged 2 commits into
mainfrom
fine-tuning-20260804

Conversation

@chrisghill

Copy link
Copy Markdown
Member

Summary

Addresses feedback from agent sessions using the architect and bundle-dev plugins, where get_deployment_logs output overflowed tool-result limits, deployment params had to be echoed back verbatim for every action, and API limits surfaced only as runtime errors.

get_deployment_logs: bounded output and easier follow/resume

  • Output now defaults to the most recent 40KB (a single Azure App Service deploy previously returned 62.8KB / 1,125 lines, overflowing MCP tool-result limits). A leading note reports when older content was elided, so truncation is never silent.
  • New tail_lines param: pass N for exactly the last N lines, -1 for the complete log, or omit for the default 40KB cap.
  • Log content is never rewritten — the returned text (after the note line) is always a verbatim suffix of the real log, including ANSI color codes.
  • Follow-mode timeouts now report the current status and explicitly instruct the agent to call again with follow=true to keep waiting. Since tail_lines composes with follow, repeat calls can use a small tail to avoid re-reading output (the SDK re-emits the full backfill on each follow; the cap bounds it).

create_deployment / propose_deployment: use_latest_params

  • New use_latest_params flag reuses the instance's saved params (from its most recent deployment) instead of requiring the agent to read get_instance.params and echo it back — the common loop for DECOMMISSION, PLAN of current config, and redeploy-as-is.
  • Mutually exclusive with params; fails with a clear error if the instance has never been deployed.

Input schema constraints for API limits that previously surfaced only at runtime

  • maxLength: 255 on description for project, environment, and component create/clone/fork/update tools (a 255-char overrun previously cost agents two blind retries), enforced by the go-sdk before the call reaches the API.
  • maxLength: 20 on creation-time identifier slugs (create_project, clone_project, create_environment, fork_environment, add_component). Lookup id fields on get/update tools are unconstrained since full identifiers like myproj-staging exceed the slug limit.
  • Fixed stale "max 12 characters" prose on project identifiers (the live API allows 20).
  • metadata.go constraint helpers refactored so enum and maxLength constraints compose on a shared inferred schema.

create_custom_attribute: documented key rules

  • Tool and key field descriptions now document that keys are unique org-wide across ALL scopes (case-insensitive) and the key format (1-64 chars, identifier-like, md- reserved), so agents pick per-scope key names up front instead of discovering the collision via the API's misleading organizationId: has already been taken error. (The error message itself will be fixed API-side.)

Test plan

  • Unit tests for tailLogs covering the default byte cap, verbatim-suffix property, single-line-exceeding-cap fallback, rune-boundary truncation, explicit tail_lines, and -1 passthrough.
  • Handler tests for snapshot tailing, follow-mode status header, use_latest_params (reuse, mutual exclusion, never-deployed), and maxLength presence on all constrained schema properties.
  • go build, go vet, gofmt, and the full go test ./... suite pass.

🤖 Generated with Claude Code

@chrisghill

Copy link
Copy Markdown
Member Author

@claude review

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown

Claude finished @chrisghill's task in 1m 41s —— View job


Code Review

  • Gather context (PR body, changed files list)
  • Read repo guidelines (no CLAUDE.md present in this repo)
  • Review mcp/tools/logs.go (tailLogs implementation) + tests
  • Review mcp/tools/deployments.go (use_latest_params, follow-mode) + tests
  • Review mcp/tools/metadata.go (schema constraint helpers) + tests
  • Review remaining touched files (components, environments, organizations, projects, go.sum)
  • Double-check Instance.Params semantics for use_latest_params edge case
  • Post final review feedback

Solid, well-scoped PR — good test coverage on the new behaviors and the descriptions/error messages are unusually careful about agent ergonomics. A few notes:

Minor: use_latest_params can't distinguish "never deployed" from "deployed with an empty params schema"

latestInstanceParams (mcp/tools/deployments.go:490-502) uses len(instance.Params) == 0 to detect "never deployed":

if len(instance.Params) == 0 {
    return nil, fmt.Errorf("%s: use_latest_params requires an instance that has been deployed before, but instance %s has no saved params — pass params explicitly", toolName, instanceID)
}

get_instance's own docs already note params are "empty until first deployed" — same ambiguity. But an instance whose bundle has an empty/trivial paramsSchema (no configurable params) would, after a real, successful deployment, legitimately have Params unmarshal to a non-nil empty map ({}), which len() can't distinguish from nil/never-deployed. For such an instance, use_latest_params: true would incorrectly fail with "has no saved params" / "requires an instance that has been deployed before" even though it has been deployed — it just has nothing to save.

This is a narrow edge case (bundles with zero configurable params aren't the common case) and pre-existing ambiguity in the underlying data, not a regression this PR introduces wholesale — but since this PR turns that ambiguous signal into a hard error (previously it was just descriptive text), it's worth a decision: either accept the edge case as acceptably rare, or special-case it if the SDK instance type exposes anything to distinguish "has a deployment" from "has saved params" (e.g. a deployment count/history field, or a schema check against paramsSchema.properties being empty). Not a blocker either way.

Everything else looks correct

  • tailLogs (mcp/tools/logs.go): the byte-cap/line-cap/-1 logic is correct, the verbatim-suffix guarantee holds, and the rune-boundary handling for the single-oversized-line case is a nice touch. Tests cover the interesting edge cases well (multibyte truncation, oversized single line, no-op when under cap).
  • Follow-mode timeout messaging (mcp/tools/deployments.go:154-165): clear instruction to retry with follow=true, and tail_lines composes correctly with both snapshot and follow paths.
  • use_latest_params mutual exclusion (mcp/tools/deployments.go:492-494): correctly checked before the API call, so passing params: {} (non-nil empty map) alongside the flag is correctly rejected rather than silently ignored.
  • metadata.go schema helpers: toolSchema/mustProp refactor cleanly lets applyEnums and applyMaxLengths compose on the same tool's schema regardless of init order. applyMaxLengths correctly limits constraints to creation-time slugs while leaving lookup id fields (e.g. myproj-staging) unconstrained.
  • create_custom_attribute docs: the org-wide/case-insensitive key collision behavior and md- reserved prefix are now documented up front, matching the stated goal of avoiding a blind API round-trip.
  • go.sum: just dedup of stale massdriver-sdk-go versions from a prior go mod tidy, consistent with pinning to v0.2.17.

Note on verification

I was not able to run go build/go vet/go test in this sandbox (tool execution required approval that wasn't available here), so I verified correctness by reading the diff and tests rather than executing them. The PR description states the full suite passes; you may want to confirm CI is green before merging.

@chrisghill
chrisghill merged commit 68ba343 into main Aug 4, 2026
5 checks passed
@chrisghill
chrisghill deleted the fine-tuning-20260804 branch August 4, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants