Skip to content

Commit 61a3e17

Browse files
committed
Add harness user-agent dimension for omnigent meta-harness
Detect the OMNIGENT environment variable and report harness/omnigent as an independent user-agent dimension, parallel to agent detection. This lets the platform see both the meta-harness (omnigent) and the underlying coding agent (e.g. claude-code) in the same request. Co-authored-by: Isaac Signed-off-by: simon <simon.faltum@databricks.com>
1 parent 4314a9b commit 61a3e17

5 files changed

Lines changed: 123 additions & 1 deletion

File tree

NEXT_CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# NEXT CHANGELOG
2+
3+
## Release v0.118.0
4+
5+
### New Features and Improvements
6+
7+
* Added a `harness` user-agent dimension that reports the omnigent meta-harness (detected via the `OMNIGENT` environment variable) independently of agent detection.
8+
9+
### Security
10+
11+
### Bug Fixes
12+
13+
### Documentation
14+
15+
### Breaking Changes
16+
17+
### Internal Changes
18+
19+
### API Changes

databricks/sdk/useragent.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
RUNTIME_KEY = "runtime"
1313
CICD_KEY = "cicd"
1414
AUTH_KEY = "auth"
15+
HARNESS_KEY = "harness"
1516

1617
_product_name = "unknown"
1718
_product_version = "0.0.0"
@@ -175,6 +176,9 @@ def to_string(
175176
agent = agent_provider()
176177
if agent:
177178
base.append(("agent", agent))
179+
harness = harness_provider()
180+
if harness:
181+
base.append((HARNESS_KEY, harness))
178182
return " ".join(f"{k}/{v}" for k, v in base)
179183

180184

@@ -329,3 +333,37 @@ def _agent_env_fallback() -> str:
329333
if not v:
330334
return ""
331335
return _sanitize_agent_value(v)[:_MAX_AGENT_FALLBACK_LEN]
336+
337+
338+
@dataclass(frozen=True)
339+
class _HarnessRecord:
340+
env_var: str
341+
product: str
342+
343+
344+
# Known agent meta-harnesses, detected independently of agents (a harness is
345+
# not an agent). Keep in sync with databricks-sdk-go and databricks-sdk-java.
346+
_KNOWN_HARNESSES: List[_HarnessRecord] = [
347+
_HarnessRecord("OMNIGENT", "omnigent"), # https://github.com/omnigent-ai/omnigent
348+
]
349+
350+
# None = not computed, "" = computed but no harness found.
351+
_harness_provider = None
352+
353+
354+
def harness_provider() -> str:
355+
"""Detect a known agent meta-harness by presence-only env var, else "".
356+
357+
Returns "multiple" if more than one matched. Cached after the first call.
358+
"""
359+
global _harness_provider
360+
if _harness_provider is not None:
361+
return _harness_provider
362+
matches = [h.product for h in _KNOWN_HARNESSES if h.env_var in os.environ]
363+
if len(matches) == 1:
364+
_harness_provider = matches[0]
365+
elif len(matches) > 1:
366+
_harness_provider = "multiple"
367+
else:
368+
_harness_provider = ""
369+
return _harness_provider

tests/test_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ def system(self):
8282
monkeypatch.setattr(useragent, "_extra", [])
8383
monkeypatch.setattr(useragent, "_cicd_provider", None)
8484
monkeypatch.setattr(useragent, "_agent_provider", None)
85+
monkeypatch.setattr(useragent, "_harness_provider", None)
8586

8687
monkeypatch.setattr(platform, "python_version", lambda: "3.0.0")
8788
monkeypatch.setattr(platform, "uname", MockUname)

tests/test_core.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ def system(self):
275275
monkeypatch.setattr(useragent, "_extra", [])
276276
monkeypatch.setattr(useragent, "_cicd_provider", None)
277277
monkeypatch.setattr(useragent, "_agent_provider", None)
278+
monkeypatch.setattr(useragent, "_harness_provider", None)
278279

279280
monkeypatch.setattr(platform, "python_version", lambda: "3.0.0")
280281
monkeypatch.setattr(platform, "uname", MockUname)

tests/test_user_agent.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,12 @@ def clean_useragent_env():
6868
original_env = os.environ.copy()
6969
os.environ.clear()
7070

71-
# Clear cached CICD and agent providers.
71+
# Clear cached CICD, agent, and harness providers.
7272
from databricks.sdk import useragent
7373

7474
useragent._cicd_provider = None
7575
useragent._agent_provider = None
76+
useragent._harness_provider = None
7677

7778
yield
7879

@@ -81,6 +82,7 @@ def clean_useragent_env():
8182
os.environ.update(original_env)
8283
useragent._cicd_provider = None
8384
useragent._agent_provider = None
85+
useragent._harness_provider = None
8486

8587

8688
def test_user_agent_cicd_no_provider(clean_useragent_env):
@@ -493,3 +495,64 @@ def test_agent_provider_cached(clean_useragent_env):
493495
os.environ["CLAUDECODE"] = "1"
494496

495497
assert useragent.agent_provider() == "cursor"
498+
499+
500+
def test_harness_provider_no_harness(clean_useragent_env):
501+
from databricks.sdk import useragent
502+
503+
assert useragent.harness_provider() == ""
504+
505+
506+
def test_harness_provider_omnigent(clean_useragent_env):
507+
os.environ["OMNIGENT"] = "1"
508+
from databricks.sdk import useragent
509+
510+
assert useragent.harness_provider() == "omnigent"
511+
512+
513+
def test_harness_provider_omnigent_empty_value_still_counts_as_set(clean_useragent_env):
514+
# Presence-only matcher: an empty value still fires.
515+
os.environ["OMNIGENT"] = ""
516+
from databricks.sdk import useragent
517+
518+
assert useragent.harness_provider() == "omnigent"
519+
520+
521+
def test_harness_provider_cached(clean_useragent_env):
522+
os.environ["OMNIGENT"] = "1"
523+
from databricks.sdk import useragent
524+
525+
assert useragent.harness_provider() == "omnigent"
526+
527+
# Change the environment: the cached result should persist.
528+
del os.environ["OMNIGENT"]
529+
530+
assert useragent.harness_provider() == "omnigent"
531+
532+
533+
def test_user_agent_string_includes_harness(clean_useragent_env):
534+
os.environ["OMNIGENT"] = "1"
535+
from databricks.sdk import useragent
536+
537+
ua = useragent.to_string()
538+
assert "harness/omnigent" in ua
539+
540+
541+
def test_user_agent_string_no_harness(clean_useragent_env):
542+
from databricks.sdk import useragent
543+
544+
ua = useragent.to_string()
545+
assert "harness/" not in ua
546+
547+
548+
def test_harness_independent_of_agent(clean_useragent_env):
549+
# omnigent spawns the real agent CLI, so both env vars are set: the UA must
550+
# carry both dimensions and omnigent must not trip the agent "multiple" signal.
551+
os.environ["CLAUDECODE"] = "1"
552+
os.environ["OMNIGENT"] = "1"
553+
from databricks.sdk import useragent
554+
555+
ua = useragent.to_string()
556+
assert "agent/claude-code" in ua
557+
assert "harness/omnigent" in ua
558+
assert useragent.agent_provider() == "claude-code"

0 commit comments

Comments
 (0)