This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new 29c6ea2372 CTR remove userAgent from connection options as per 
previous devlist across all GLVs
29c6ea2372 is described below

commit 29c6ea2372ff624a36ece3a33549182e4af03acc
Author: Yang Xia <[email protected]>
AuthorDate: Wed Oct 21 18:31:09 2026 -0700

    CTR remove userAgent from connection options as per previous devlist across 
all GLVs
    
    Removed the per-request userAgent request option from Java, Python, Go,
    JavaScript and .NET. It was sent as a request body field that Gremlin 
Server never read. The User-Agent header, controlled by 
enableUserAgentOnConnect, is now the only place the user agent is sent.
    
    Assisted-by: Kiro:claude-opus-5-5
---
 CHANGELOG.asciidoc                                  |  1 +
 docs/src/reference/gremlin-variants.asciidoc        | 16 ++++++++--------
 docs/src/upgrade/release-4.x.x.asciidoc             | 21 +++++++++++++++++++++
 .../Gremlin.Net/Driver/Messages/RequestMessage.cs   | 11 -----------
 gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs     |  6 ------
 .../driver/remote/DriverRemoteConnectionTest.java   |  1 -
 gremlin-go/driver/client.go                         |  1 -
 gremlin-go/driver/request.go                        | 14 --------------
 gremlin-go/driver/requestOptions.go                 |  8 --------
 gremlin-go/driver/requestOptions_test.go            |  4 ----
 gremlin-go/driver/request_test.go                   |  6 ------
 gremlin-js/gremlin-javascript/lib/driver/client.ts  |  1 -
 .../lib/driver/driver-remote-connection.ts          |  1 -
 .../main/python/gremlin_python/driver/request.py    |  2 +-
 .../driver/test_driver_remote_connection.py         |  1 -
 .../org/apache/tinkerpop/gremlin/util/Tokens.java   |  6 ------
 16 files changed, 31 insertions(+), 69 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index de9c504422..0f9d34139f 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -32,6 +32,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Fixed a `NullPointerException` when rolling back a transaction on a 
`TinkerStorageGraph` that has a vertex index but no edge index.
 * Added a pluggable storage layer to `TinkerStorageGraph` that durably 
persists each committed transaction to disk.
 * Removed automatic persistence from `TinkerMemoryGraph`, which is now purely 
in-memory and ignores `gremlin.tinkergraph.graphLocation`/`graphFormat`. Use 
`TinkerStorageGraph` for durability or `g.io()` for interchange.
+* Removed the per-request `userAgent` option from all drivers so the user 
agent is sent only as the `User-Agent` header controlled by 
`enableUserAgentOnConnect`.
 
 [[release-4-0-0-beta-3]]
 === TinkerPop 4.0.0-beta.3 (July 20, 2026)
diff --git a/docs/src/reference/gremlin-variants.asciidoc 
b/docs/src/reference/gremlin-variants.asciidoc
index 70b88a0fb5..99de3c9d80 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -242,7 +242,7 @@ Some connection options can also be set on individual 
requests made through the
 results, err := g.With("timeoutMillis", 500).V().Out("knows").ToList()
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `userAgent` and
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults` and
 `timeoutMillis`.
 
 NOTE: When submitting traversals through `DriverRemoteConnection`, 
`bulkResults` defaults to `true` per-request
@@ -531,7 +531,7 @@ options := new(RequestOptionsBuilder).
 resultSet, err := client.SubmitWithOptions("g.V(x).count()", options)
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `userAgent`,
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`,
 `timeoutMillis` and `materializeProperties`.
 `RequestOptions` may also contain a map of query `parameters` to be applied to 
the supplied
 traversal string.
@@ -2012,7 +2012,7 @@ Some connection options can also be set on individual 
requests made through the
 const vertices = await g.with_('timeoutMillis', 500).V().out('knows').toList()
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `requestId`, `userAgent`,
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `requestId`,
 `bulkResults`, `materializeProperties` and `timeoutMillis`.
 
 NOTE: When submitting traversals through `DriverRemoteConnection`, 
`bulkResults` defaults to `true` per-request
@@ -2360,7 +2360,7 @@ this feature is to set a per-request override to the 
`timeoutMillis` so that it
 const result = await client.submit("g.V().repeat(both()).times(100)", null, { 
timeoutMillis: 5000 })
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `requestId`, `userAgent`,
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `requestId`,
 `bulkResults`, `materializeProperties` and `timeoutMillis`.
 
 IMPORTANT: The preferred method for setting a per-request timeout for scripts 
is demonstrated above, but a script may
@@ -2764,7 +2764,7 @@ For instance to set request timeout to 500 milliseconds:
 var l = g.With(Tokens.ArgsTimeoutMillis, 
500).V().Out("knows").Count().ToList();
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `userAgent`,
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`,
 `materializeProperties`, and `timeoutMillis`. These options are available as 
constants on the `Gremlin.Net.Driver.Tokens`
 class.
 
@@ -3039,7 +3039,7 @@ feature is to set a per-request override to the 
`timeoutMillis` so that it only
 
include::../../../gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Docs/Reference/GremlinVariantsTests.cs[tags=submittingScriptsWithTimeout]
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `userAgent`, `materializeProperties`
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `materializeProperties`
 and `timeoutMillis`. These options are available as constants on the 
`Gremlin.Net.Driver.Tokens` class.
 
 [[gremlin-dotnet-streaming]]
@@ -3473,7 +3473,7 @@ vertices = g.with_('timeoutMillis', 
500).V().out('knows').to_list()
 ----
 
 The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `language`,
-`materializeProperties`, `userAgent`, and `timeoutMillis`.
+`materializeProperties`, and `timeoutMillis`.
 
 NOTE: When submitting traversals through `DriverRemoteConnection`, 
`bulkResults` defaults to `True` per-request
 to optimize result transfer. This does not apply to direct `Client.submit()` 
calls, where `bulkResults` must be
@@ -3837,7 +3837,7 @@ this feature is to set a per-request override to the 
`timeoutMillis` so that it
 result_set = client.submit('g.V().repeat(both()).times(100)', 
request_options={'timeoutMillis': 5000})
 ----
 
-The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `requestId`, `userAgent`,
+The following options are allowed on a per-request basis in this fashion: 
`batchSize`, `bulkResults`, `requestId`,
 `materializeProperties` and `timeoutMillis`.
 
 IMPORTANT: The preferred method for setting a per-request timeout for scripts 
is demonstrated above, but a script may
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc 
b/docs/src/upgrade/release-4.x.x.asciidoc
index 2222688b14..16e98aa801 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -149,6 +149,24 @@ which opens a `TinkerStorageGraph` with disk storage.
 
 See: 
link:https://tinkerpop.apache.org/docs/4.0.0/reference/#tinkergraph-gremlin-persistence[TinkerGraph
 Persistence]
 
+==== User Agent Only in the Request Header
+
+The user agent is now sent only as the `User-Agent` HTTP header. Every driver 
sends that header by default, and the
+connection-level `enableUserAgentOnConnect` option (cased idiomatically per 
language) turns it on or off. The
+per-request `userAgent` field that some drivers could place in the request 
body has been removed. Gremlin Server never
+read that field, so requests behave exactly as before.
+
+Code that set the per-request field no longer compiles or no longer has an 
effect, and the line can simply be deleted:
+
+* Java: the unused `Tokens.ARGS_USER_AGENT` constant is removed.
+* Python: `userAgent` is no longer a recognized `request_options` key or 
`with_()` option, and is ignored if supplied.
+* .NET: `RequestMessage.Builder.AddUserAgent()` and `Tokens.ArgsUserAgent` are 
removed. `With("userAgent", ...)` is
+still forwarded like any other custom `With()` key, but Gremlin Server ignores 
it.
+* Go: `RequestOptionsBuilder.SetUserAgent()` is removed, and 
`With("userAgent", ...)` is ignored.
+* JavaScript: the `userAgent` field is removed from `RequestOptions`, and 
`with_('userAgent', ...)` is ignored.
+
+See: 
link:https://lists.apache.org/thread/clyxxp8t6mg3y7y8nj1z48l19j7pk2v8[\[DISCUSS\]
 Only Support User Agent in Request Header]
+
 === Upgrading for Providers
 
 ==== Graph System Providers
@@ -162,6 +180,9 @@ the job of a `TinkerStorage` engine on `TinkerStorageGraph`.
 
 ==== Graph Driver Providers
 
+Drivers should send the user agent only as the `User-Agent` request header, in 
the format described in the provider
+documentation, and should not add a `userAgent` field to the request body.
+
 [llms-summary="Upgrade notes for the TinkerPop 4.0.0-beta.3 release: 
user-facing changes including declarative pattern matching improvements and 
other 4.0 features."]
 == TinkerPop 4.0.0-beta.3
 
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs 
b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs
index c99d046c8f..3290fe958a 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Messages/RequestMessage.cs
@@ -202,17 +202,6 @@ namespace Gremlin.Net.Driver.Messages
                 return this;
             }
 
-            /// <summary>
-            ///     Sets the user agent for this request.
-            /// </summary>
-            /// <param name="userAgent">The user agent string.</param>
-            /// <returns>The <see cref="Builder" />.</returns>
-            public Builder AddUserAgent(string userAgent)
-            {
-                _fields[Tokens.ArgsUserAgent] = userAgent;
-                return this;
-            }
-
             /// <summary>
             ///     Sets the bulk results option for this request.
             /// </summary>
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs 
b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
index 2f1b330346..ff4b9ffda4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/Tokens.cs
@@ -57,12 +57,6 @@ namespace Gremlin.Net.Driver
         /// </summary>
         public const string ArgsGremlin = "gremlin";
 
-        /// <summary>
-        ///     Argument name that allows a value that is a custom string that 
the user can pass to a server that
-        ///     might accept it for purpose of identifying the kind of client 
it came from.
-        /// </summary>
-        public const string ArgsUserAgent = "userAgent";
-
         /// <summary>
         ///     Argument name that allows definition of the flavor of Gremlin 
used (e.g. gremlin-groovy) to process the request.
         /// </summary>
diff --git 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
index 2d9e0a8d18..a0986fd24d 100644
--- 
a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
+++ 
b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteConnectionTest.java
@@ -56,7 +56,6 @@ public class DriverRemoteConnectionTest {
                         with("y", 100).
                         with(Tokens.ARGS_BATCH_SIZE, 1000).
                         with(Tokens.TIMEOUT_MILLIS, 100000L).
-                        with(Tokens.ARGS_USER_AGENT, "test").
                         V().asAdmin().getGremlinLang());
         assertEquals(1000, options.getBatchSize().get().intValue());
         assertEquals(100000L, options.getTimeoutMillis().get().longValue());
diff --git a/gremlin-go/driver/client.go b/gremlin-go/driver/client.go
index d5345393ad..61144aeb00 100644
--- a/gremlin-go/driver/client.go
+++ b/gremlin-go/driver/client.go
@@ -326,7 +326,6 @@ func applyOptionsConfig(builder *RequestOptionsBuilder, 
config map[string]interf
        setterMap := map[string]string{
                "timeoutMillis":         "SetTimeoutMillis",
                "batchSize":             "SetBatchSize",
-               "userAgent":             "SetUserAgent",
                "materializeProperties": "SetMaterializeProperties",
                "bulkResults":           "SetBulkResults",
        }
diff --git a/gremlin-go/driver/request.go b/gremlin-go/driver/request.go
index cbe9f19e39..73dbc6d507 100644
--- a/gremlin-go/driver/request.go
+++ b/gremlin-go/driver/request.go
@@ -64,10 +64,6 @@ func MakeStringRequest(stringGremlin string, traversalSource 
string, requestOpti
                newFields["batchSize"] = requestOptions.batchSize
        }
 
-       if requestOptions.userAgent != "" {
-               newFields["userAgent"] = requestOptions.userAgent
-       }
-
        if requestOptions.materializeProperties != "" {
                newFields["materializeProperties"] = 
requestOptions.materializeProperties
        }
@@ -85,13 +81,3 @@ func MakeStringRequest(stringGremlin string, traversalSource 
string, requestOpti
                Fields:  newFields,
        }
 }
-
-// allowedReqArgs contains the arguments that will be extracted from the
-// bytecode and sent with the request.
-var allowedReqArgs = map[string]bool{
-       "timeoutMillis":         true,
-       "batchSize":             true,
-       "userAgent":             true,
-       "materializeProperties": true,
-       "bulkResults":           true,
-}
diff --git a/gremlin-go/driver/requestOptions.go 
b/gremlin-go/driver/requestOptions.go
index cc65fb6c93..47a43740fc 100644
--- a/gremlin-go/driver/requestOptions.go
+++ b/gremlin-go/driver/requestOptions.go
@@ -22,7 +22,6 @@ package gremlingo
 type RequestOptions struct {
        timeoutMillis         int
        batchSize             int
-       userAgent             string
        parametersString      string
        materializeProperties string
        bulkResults           *bool
@@ -32,7 +31,6 @@ type RequestOptions struct {
 type RequestOptionsBuilder struct {
        timeoutMillis         int
        batchSize             int
-       userAgent             string
        parameters            map[string]interface{}
        parametersString      string
        materializeProperties string
@@ -50,11 +48,6 @@ func (builder *RequestOptionsBuilder) SetBatchSize(batchSize 
int) *RequestOption
        return builder
 }
 
-func (builder *RequestOptionsBuilder) SetUserAgent(userAgent string) 
*RequestOptionsBuilder {
-       builder.userAgent = userAgent
-       return builder
-}
-
 func (builder *RequestOptionsBuilder) SetParameters(parameters 
map[string]interface{}) *RequestOptionsBuilder {
        if builder.parametersString != "" {
                panic("cannot mix SetParameters() with SetParametersString()")
@@ -102,7 +95,6 @@ func (builder *RequestOptionsBuilder) Create() 
RequestOptions {
 
        requestOptions.timeoutMillis = builder.timeoutMillis
        requestOptions.batchSize = builder.batchSize
-       requestOptions.userAgent = builder.userAgent
        requestOptions.materializeProperties = builder.materializeProperties
        requestOptions.bulkResults = builder.bulkResults
        requestOptions.transactionId = builder.transactionId
diff --git a/gremlin-go/driver/requestOptions_test.go 
b/gremlin-go/driver/requestOptions_test.go
index 25b5408a3a..4e691322cb 100644
--- a/gremlin-go/driver/requestOptions_test.go
+++ b/gremlin-go/driver/requestOptions_test.go
@@ -34,10 +34,6 @@ func TestRequestOptions(t *testing.T) {
                r := new(RequestOptionsBuilder).SetBatchSize(123).Create()
                assert.Equal(t, 123, r.batchSize)
        })
-       t.Run("Test RequestOptionsBuilder with custom userAgent", func(t 
*testing.T) {
-               r := 
new(RequestOptionsBuilder).SetUserAgent("TestUserAgent").Create()
-               assert.Equal(t, "TestUserAgent", r.userAgent)
-       })
        t.Run("Test RequestOptionsBuilder with custom materializeProperties", 
func(t *testing.T) {
                r := 
new(RequestOptionsBuilder).SetMaterializeProperties("TestMaterializeProperties").Create()
                assert.Equal(t, "TestMaterializeProperties", 
r.materializeProperties)
diff --git a/gremlin-go/driver/request_test.go 
b/gremlin-go/driver/request_test.go
index ca75ac6415..46645943b0 100644
--- a/gremlin-go/driver/request_test.go
+++ b/gremlin-go/driver/request_test.go
@@ -46,12 +46,6 @@ func TestRequest(t *testing.T) {
                assert.Equal(t, 123, r.Fields["batchSize"])
        })
 
-       t.Run("Test makeStringRequest() with custom userAgent", func(t 
*testing.T) {
-               r := MakeStringRequest("g.V()", "g",
-                       
new(RequestOptionsBuilder).SetUserAgent("TestUserAgent").Create())
-               assert.Equal(t, "TestUserAgent", r.Fields["userAgent"])
-       })
-
        t.Run("Test makeStringRequest() with bulkResults", func(t *testing.T) {
                r := MakeStringRequest("g.V()", "g",
                        
new(RequestOptionsBuilder).SetBulkResults(true).Create())
diff --git a/gremlin-js/gremlin-javascript/lib/driver/client.ts 
b/gremlin-js/gremlin-javascript/lib/driver/client.ts
index 0686d4d0e8..cd7893cb6d 100644
--- a/gremlin-js/gremlin-javascript/lib/driver/client.ts
+++ b/gremlin-js/gremlin-javascript/lib/driver/client.ts
@@ -27,7 +27,6 @@ export type RequestOptions = {
   accept?: string;
   timeoutMillis?: number;
   batchSize?: number;
-  userAgent?: string;
   materializeProperties?: string;
   bulkResults?: boolean;
   params?: Record<string, any>;
diff --git 
a/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts 
b/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts
index d61fde3fd4..af6c18fcf3 100644
--- a/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts
+++ b/gremlin-js/gremlin-javascript/lib/driver/driver-remote-connection.ts
@@ -84,7 +84,6 @@ export default class DriverRemoteConnection extends 
RemoteConnection {
         'timeoutMillis',
         'batchSize',
         'requestId',
-        'userAgent',
         'materializeProperties',
         'bulkResults',
       ];
diff --git a/gremlin-python/src/main/python/gremlin_python/driver/request.py 
b/gremlin-python/src/main/python/gremlin_python/driver/request.py
index 0b72fa1aa6..4e75ffb8f8 100644
--- a/gremlin-python/src/main/python/gremlin_python/driver/request.py
+++ b/gremlin-python/src/main/python/gremlin_python/driver/request.py
@@ -24,5 +24,5 @@ RequestMessage = collections.namedtuple(
     'RequestMessage', ['fields', 'gremlin'])
 
 Tokens = ['batchSize', 'parameters', 'g', 'gremlin', 'language',
-          'materializeProperties', 'timeoutMillis', 'userAgent', 'bulkResults',
+          'materializeProperties', 'timeoutMillis', 'bulkResults',
           'transactionId']
diff --git 
a/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py
 
b/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py
index 61279f34f2..adf131866d 100644
--- 
a/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py
+++ 
b/gremlin-python/src/main/python/tests/integration/driver/test_driver_remote_connection.py
@@ -60,7 +60,6 @@ class TestDriverRemoteConnection(object):
                                                         
"test").V(GValue('ids', [1, 2, 3])).count()
         assert remote_connection.extract_request_options(t.gremlin_lang) == 
{'batchSize': 100,
                                                                              
'timeoutMillis': 1000,
-                                                                             
'userAgent': 'test',
                                                                              
'bulkResults': True,
                                                                              
'parameters': "['ids':[1,2,3]]"}
         assert 3 == t.to_list()[0]
diff --git 
a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java 
b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
index e4acba5d55..27a110d259 100644
--- a/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
+++ b/gremlin-util/src/main/java/org/apache/tinkerpop/gremlin/util/Tokens.java
@@ -97,12 +97,6 @@ public final class Tokens {
      */
     public static final String BULK_RESULTS = "bulkResults";
 
-    /**
-     * A value that is a custom string that the user can pass to a server that 
might accept it for purpose of
-     * identifying the kind of client it came from.
-     */
-    public static final String ARGS_USER_AGENT = "userAgent";
-
     /**
      * Argument name for the transaction ID used to track multi-request 
transactions over HTTP.
      * The transaction ID is a UUID generated by the client at transaction 
begin time and included

Reply via email to