Skip to content

[agentbricks] Keep the databricks CLI's own output out of --output json stdout - #762

Merged
elainewang-db merged 2 commits into
databricks:mainfrom
elainewang-db:agentbricks-deploy-json-stdout
Oct 16, 2026
Merged

elainewang-db merged 2 commits into
databricks:mainfrom
elainewang-db:agentbricks-deploy-json-stdout

Conversation

@elainewang-db

@elainewang-db elainewang-db commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

agentbricks --output json deploy printed more than its JSON payload on stdout, so a script reading the payload failed with JSONDecodeError: Extra data. Two sources:

  • deploy runs databricks sync and databricks apps deploy without capturing their output, so the sync progress (Action: PUT: …, Uploaded …, Initial Sync Complete) and the App object apps deploy prints went to stdout.
  • When it creates an App through the CLI (no tool needs request-user scopes), or resizes it, deploy relayed the App object apps create / create-update printed through Reporter.echo, which writes to stdout.

The fix sends both to stderr:

  • The databricks CLI runner gets a to_stderr flag that sends an uncaptured command's output to stderr. sync, apps deploy, apps start, apps stop and apps delete use it, so deploy and deployments start/stop/delete keep stdout for their --output json payload. apps logs and apps run-local still print to stdout, since their output is what the user asked for.
  • AppProvisioner relays the apps create / create-update output with Reporter.note (stderr) instead of Reporter.echo.

In normal output, all of this still shows in the terminal.

Before / after

The same project deployed with agentbricks --output json deploy ab762demo --source <project>, stdout and stderr captured to separate files, then stdout parsed with json.load.

Before (main at 966efe7): stdout is 117 lines. The App object from apps create, then the databricks sync progress, then the deploy payload:

$ agentbricks --output json deploy ab762demo --source ./ab762demo > out.json 2> err.txt
$ cat out.json
{
  "app_status": {
    "message": "App has status: App has not been deployed yet. Run your app by deploying source code",
    "state": "UNAVAILABLE"
  },
  ...
  "url": "https://agent-bricks-ab762demo-3272836215725701.aws.databricksapps.com"
}
Action: PUT: .agent/skills/agent-bricks-workflow/SKILL.md, .agents/skills/agent-bricks-workflow/SKILL.md, ...
Uploaded agent/tools
Uploaded .agent/skills/agent-bricks-workflow
Uploaded runtime
...
{
  "deployment": "agent-bricks-ab762demo",
  ...
}
$ python -c 'import json; json.load(open("out.json"))'
json.decoder.JSONDecodeError: Extra data: line 30 column 1 (char 1070)

After (this PR at 6f5555a, redeploying the same App): stdout is only the deploy payload, and it parses. The sync progress and the App object from apps deploy go to stderr:

$ agentbricks --output json deploy ab762demo --source ./ab762demo > out.json 2> err.txt
$ cat out.json
{
  "deployment": "agent-bricks-ab762demo",
  "url": "https://agent-bricks-ab762demo-3272836215725701.aws.databricksapps.com",
  "memory_store": "ab762demo-hhknkf-memory",
  "session_store": "ab762demo-hhknkf-sessions",
  "trace_grant": "granted",
  "store_grant": "granted",
  ...
}
$ python -c 'import json; json.load(open("out.json"))'   # no error
$ cat err.txt
Action: PUT: app.yaml
Uploaded app.yaml
Initial Sync Complete
{
  "create_time": "2026-10-16T21:24:02Z",
  "creator": "elaine.wang@databricks.com",
  ...

The before run was the App's first deploy (full upload); the after run was a redeploy, so its sync is shorter.

Testing

  • pytest tests/unit_tests: 1878 passed. New tests: the runner sends output to fd 2 when to_stderr is set; each of the five lifecycle commands sets it; the provisioner relays the apps create and create-update output with note, not echo. Two existing tests' expected apps delete call now include to_stderr=True.
  • ruff passes; ty reports the same diagnostics as main.
  • E2E, from [l] [agentbricks] Add pytest E2E suites #706's suites on the integration workspace, which read deploy --output json: without this PR, every deploy test failed to parse deploy's output. With it, all 6 tests pass (test_deploy, test_memory, test_sessions, test_tracing, test_dev, test_tools_remove) in 6 min 5 s.

This pull request and its description were written by Isaac.

…on stdout

Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>

@jamesbxwu jamesbxwu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to help understand the behavioral change better, can you include a before / after screenshot in the PR description?

@elainewang-db
elainewang-db merged commit 42fd131 into databricks:main Oct 16, 2026
54 checks passed
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.

2 participants