Repository navigation
Tell AI agents to pass the device code login on to the user - #7235
maksim-zuev-db wants to merge 6 commits into
Conversation
|
Commit: Regression test reportSelected 6 changed tests (limit=20, 0 not selected) 6 tests: regression=6 unreleased=0 coverage=0 failing=0
TestAccept/cmd/auth/login/device-code/non-interactive/concurrent: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): TestAccept/cmd/auth/login/device-code/non-interactive/errors: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): TestAccept/cmd/auth/login/device-code/non-interactive/flags: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): same output as main (aed6702) TestAccept/cmd/auth/login/device-code/non-interactive/nominal: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): same output as main (aed6702) TestAccept/cmd/auth/login/device-code/unsupported-host: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): same output as main (aed6702) TestAccept/cmd/auth/logout/pending-device-code-login: branch ✅ | main (aed6702) ❌ | latest (v1.23.0) ❌main (aed6702): latest (v1.23.0): same output as main (aed6702) |
Integration test reportCommit: f52b31d
Top 6 slowest tests (at least 2 minutes):
|
6636d4c to
03b79ec
Compare
03b79ec to
35d4fe6
Compare
35d4fe6 to
c8a6169
Compare
c8a6169 to
03acd36
Compare
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>
The device code login built the "Note for AI agents (<name>): " prefix by hand, like AgentNotice does. agent.Note now adds it for both, and returns an empty string when no agent is detected. AgentNotice prints the same text as before. Co-authored-by: Isaac <no-reply@databricks.com>
An agent that runs the login in a terminal, e.g. through a pseudo-terminal, got the interactive prompt without the note, so nothing told it to pass the login on to the user. The note is now part of the approval instructions that both logins print. The prompt tests clear the agent environment, so that running them from an agent does not change the output. Co-authored-by: Isaac <no-reply@databricks.com>
The interactive device code login printed the note of the non-interactive one, which tells the agent to ask the user for the confirmation code but not what to do with it. That login waits for the code at its prompt, so its note now tells the agent to enter the code there. Co-authored-by: Isaac <no-reply@databricks.com>
Co-authored-by: Isaac <no-reply@databricks.com>
03acd36 to
46f6bad
Compare
Each note is used once, so it moves next to its use. Co-authored-by: Isaac <no-reply@databricks.com>
simonfaltum
left a comment
There was a problem hiding this comment.
Thanks, the note reads well and AgentNotice prints the same text as before. The main thing is the terminal-flow note, which I don't think will work for agents (inline). The rest are small.
| agentNote := deviceCodeAgentNote + "Ask the user for the confirmation code their browser shows, and enter it\n" + | ||
| `at the "Confirmation code" prompt of this command.` |
There was a problem hiding this comment.
An agent won't have an interactive terminal, so I don't think this note will work for it. Without a terminal it already gets the two-step flow and never sees this text. If the command does run in a PTY (some IDE agent terminals), the agent usually can't type into a running command, so it waits at the prompt until the login times out.
Could agent detection pick the two-step flow (start, then rerun with --user-code and --confirmation-code) even when stdin is a terminal? Then this variant of the note can go, along with the README line that says agent detection doesn't pick the flow. (If the note stays, "Confirmation code" here duplicates the AskCancellable label below, and .agents/rules/style-guide-go.md asks for a shared constant.)
| return fmt.Errorf("store pending login: %w", err) | ||
| } | ||
| cmdio.LogString(ctx, strings.Join(append(approvalInstructions(*da), | ||
| agentNote := deviceCodeAgentNote + "Ask the user for the confirmation code their browser shows." |
There was a problem hiding this comment.
[nice to have] In the two-step flow the agent runs step two, so it's also the one that reads the wrong-code error in complete() (L244): "Check the confirmation code and approve the login if you haven't, then rerun this command." Read literally, that tells the agent to approve the login, which this note says it must not do. It shows up whenever the user passes on a wrong code or hasn't approved yet. Could you add an agent note there, e.g. agent.AgentNote("ask the user to approve the login and to check the confirmation code. Do not approve it yourself."), or reword it to "make sure the login was approved in the browser"? The text comes from #7220, so fixing it there works too.
| // Note: use of this function is incompatible with parallel execution. | ||
| func SetAgent(t TestingT, agent string) { | ||
| NullEnvironment(t) | ||
| if agent != "" { |
There was a problem hiding this comment.
[nit] SetAgent(t, "") only clears the environment through NullEnvironment and never calls t.Setenv, so a test that also calls t.Parallel() won't panic, even though the comment says parallel use isn't supported. Calling t.Setenv("AGENT", agent) unconditionally behaves the same (with nothing else set, the SDK treats an empty AGENT as no agent) and adds the guard.
| trace print_requests.py --oneline //oidc/v1/device/auth //oidc/v1/token | ||
|
|
||
| title "An AI agent gets notes on passing the login on to the user\n" | ||
| trace AGENT=test-agent $CLI auth login --host $DATABRICKS_HOST --profile agent --use-device-code |
There was a problem hiding this comment.
[nit] This is the first acceptance output that depends on agent detection, and the runner's unset list in acceptance/acceptance_test.go is missing PI_CODING_AGENT, which SDK v0.191.0 detects. When the suite runs inside Pi, the note says (pi) instead of (test-agent) and this test fails. Adding PI_CODING_AGENT to that list fixes it. libs/aitools/agents/hint_test.go has the same gap and could switch to testutil.SetAgent in a follow-up.
Stacked on #7220.
Changes
When an AI agent is detected (
useragent.AgentProvider()), device code login prints a note after the user code that tells the agent to give the URL and the code to the user, not to open the URL or approve the login itself, and to ask the user for the confirmation code. In the interactive login, the note also tells the agent to enter the code at theConfirmation codeprompt. Agent detection does not change the flow.The note uses the new
agent.AgentNote, whichAgentNoticenow uses too, with its text unchanged. The newtestutil.SetAgentkeeps the agent running the tests out of them.Why
The login must be approved by the user, but an agent that runs it gets the URL and the code and could try to approve it itself, or not pass it on. Split out of #7220 to keep that PR smaller.
Tests
The
device-code/non-interactive/nominalacceptance test runs both steps withAGENTset.TestPromptForConfirmationCode_Agentchecks the interactive note, andlibs/agenttests coverAgentNoteandAgentNotice.This pull request and its description were written by Isaac.