Skip to content

Commit c8a6169

Browse files
maksim-zuev-dbIsaac
andcommitted
Tell AI agents to pass the device code login on to the user
When an AI agent is detected, the first step of the non-interactive login also prints a note that tells it to give the URL and the user code to the user, not to approve the login itself, and to ask the user for the confirmation code. Co-authored-by: Isaac <no-reply@databricks.com>
1 parent 6b84666 commit c8a6169

6 files changed

Lines changed: 60 additions & 3 deletions

File tree

‎acceptance/cmd/auth/login/device-code/non-interactive/nominal/out.databrickscfg‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,8 @@ auth_type = databricks-cli
88

99
[__settings__]
1010
default_profile = test
11+
12+
[agent]
13+
host = [DATABRICKS_URL]
14+
workspace_id = [WORKSPACE_ID]
15+
auth_type = databricks-cli

‎acceptance/cmd/auth/login/device-code/non-interactive/nominal/output.txt‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,23 @@ Profile test was successfully saved
9191
{"method": "POST", "path": "/oidc/v1/token", "raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-2&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"}
9292
{"method": "POST", "path": "/oidc/v1/device/auth", "raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"}
9393
{"method": "POST", "path": "/oidc/v1/token", "raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-3&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"}
94+
95+
=== An AI agent gets notes on passing the login on to the user
96+
97+
>>> AGENT=test-agent [CLI] auth login --host [DATABRICKS_URL] --profile agent --use-device-code
98+
Using a browser on another device, visit:
99+
[DATABRICKS_URL]/device/verification
100+
101+
And enter the code:
102+
WDJB-MJHT
103+
104+
Note for AI agents (test-agent): give the URL and the code above to the user.
105+
Do not open the URL or approve the login yourself: the user must approve it.
106+
Ask the user for the confirmation code their browser shows.
107+
108+
Once finished, complete the login by running the same command with
109+
--user-code WDJB-MJHT and --confirmation-code set to the confirmation code
110+
provided in your browser.
111+
112+
>>> AGENT=test-agent [CLI] auth login --host [DATABRICKS_URL] --profile agent --use-device-code --user-code WDJB-MJHT --confirmation-code FTFA-QQKY
113+
Profile agent was successfully saved

‎acceptance/cmd/auth/login/device-code/non-interactive/nominal/script‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,9 @@ trace $CLI auth login --profile test --use-device-code --user-code WDJB-MJHT --c
3131
trace cache_keys
3232
trace print_requests.py --oneline //oidc/v1/device/auth //oidc/v1/token
3333

34+
title "An AI agent gets notes on passing the login on to the user\n"
35+
trace AGENT=test-agent $CLI auth login --host $DATABRICKS_HOST --profile agent --use-device-code
36+
trace AGENT=test-agent $CLI auth login --host $DATABRICKS_HOST --profile agent --use-device-code --user-code WDJB-MJHT --confirmation-code FTFA-QQKY
37+
3438
# Track the .databrickscfg file that was created to surface changes.
3539
mv "./home/.databrickscfg" "./out.databrickscfg"

‎cmd/auth/README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ in two steps instead:
120120
flags exchanges the pending device code instead of requesting a new one,
121121
and the rest of the login runs as usual.
122122

123+
Agent detection (`useragent.AgentProvider()`) does not pick the flow. It only
124+
adds a note to the first step's output that tells the agent to pass the login
125+
on to the user.
126+
123127
The pending login is a token store entry with `PendingLogin` set instead of a
124128
token. Its key is the login's cache key (the profile name, or the host without
125129
a profile) with a `#device-code` suffix, so the target's current token keeps

‎cmd/auth/login_device_code.go‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/databricks/cli/libs/databrickscfg/profile"
1313
"github.com/databricks/cli/libs/env"
1414
"github.com/databricks/cli/libs/log"
15+
"github.com/databricks/databricks-sdk-go/useragent"
1516
"github.com/spf13/cobra"
1617
"golang.org/x/oauth2"
1718
)
@@ -169,17 +170,30 @@ func (l nonInteractiveDeviceCodeLogin) start(ctx context.Context) error {
169170
if err != nil {
170171
return fmt.Errorf("store pending login: %w", err)
171172
}
172-
cmdio.LogString(ctx, strings.Join([]string{
173+
lines := []string{
173174
"Using a browser on another device, visit:",
174175
da.VerificationURI,
175176
"",
176177
"And enter the code:",
177178
formatCode(da.UserCode),
178179
"",
180+
}
181+
// An agent passes the login on to the user, who approves it in the
182+
// browser.
183+
if agent := useragent.AgentProvider(); agent != "" {
184+
lines = append(lines,
185+
"Note for AI agents ("+agent+"): give the URL and the code above to the user.",
186+
"Do not open the URL or approve the login yourself: the user must approve it.",
187+
"Ask the user for the confirmation code their browser shows.",
188+
"",
189+
)
190+
}
191+
lines = append(lines,
179192
"Once finished, complete the login by running the same command with",
180-
"--user-code " + formatCode(da.UserCode) + " and --confirmation-code set to the confirmation code",
193+
"--user-code "+formatCode(da.UserCode)+" and --confirmation-code set to the confirmation code",
181194
"provided in your browser.",
182-
}, "\n"))
195+
)
196+
cmdio.LogString(ctx, strings.Join(lines, "\n"))
183197
return nil
184198
}
185199

‎docs/device-code-login.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ Profile my-profile was successfully saved
8585
confirmation code. It saves the profile and the token. Without
8686
`--profile`, it only stores the token for the host.
8787

88+
When the CLI detects an AI agent, it also prints a note that tells the agent to
89+
pass the URL and the code on to you, not to approve the login itself, and to
90+
ask you for the confirmation code:
91+
92+
```console
93+
Note for AI agents (claude-code): give the URL and the code above to the user.
94+
Do not open the URL or approve the login yourself: the user must approve it.
95+
Ask the user for the confirmation code their browser shows.
96+
```
97+
8898
The pending login stays on your machine, so a confirmation code that ends up
8999
somewhere else, such as an agent's conversation, cannot complete the login on
90100
another machine.

0 commit comments

Comments
 (0)