Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9f1791a
add new lluna client
namrataghadi-galileo May 6, 2026
8d2227d
fix the url
namrataghadi-galileo May 7, 2026
db02db8
Merge branch 'main' into feature/64546-add-new-luna-client
namrataghadi-galileo May 11, 2026
0cce0bf
feat(galileo): support internal scorer auth
namrataghadi-galileo May 12, 2026
dd252be
add auth and update schema
namrataghadi-galileo May 12, 2026
74fcbeb
fix(galileo): align luna scorer response schema
namrataghadi-galileo May 12, 2026
7b0a15d
update the schemas and corresponding tests
namrataghadi-galileo May 13, 2026
523524d
update the schemas for scorer
namrataghadi-galileo May 14, 2026
34f430d
update luna client schemas
namrataghadi-galileo May 14, 2026
ad0b2dc
fix tests
namrataghadi-galileo May 14, 2026
81cea04
remove unwanted fields
namrataghadi-galileo May 14, 2026
f3cf8f7
remove project_id from evaluator config
namrataghadi-galileo May 14, 2026
9cf463a
Merge branch 'main' into feature/64546-add-new-luna-client
namrataghadi-galileo May 15, 2026
025f96f
add evaluator context
namrataghadi-galileo May 15, 2026
15e7a01
remove evaluation context
namrataghadi-galileo May 15, 2026
a06d3f1
add tests for coverage
namrataghadi-galileo May 15, 2026
c8662f7
coverage
namrataghadi-galileo May 16, 2026
9a94bba
move coervagera
namrataghadi-galileo May 16, 2026
f0d11b7
failing test
namrataghadi-galileo May 16, 2026
f683dda
add input text that goes into controls evaluators
namrataghadi-galileo May 18, 2026
7210fc1
add docstring
namrataghadi-galileo May 18, 2026
81a5f1d
Merge branch 'main' into feature/64546-add-new-luna-client
namrataghadi-galileo May 19, 2026
8c7ced3
feat(server): allow host-owned logging setup
abhinav-galileo May 19, 2026
831e8ce
feat(server): add control clone-and-bind endpoint
abhinav-galileo May 19, 2026
194613a
Merge branch 'feature/64546-add-new-luna-client' into test-end-to-end-1
namrataghadi-galileo May 20, 2026
42e1d3e
Merge branch 'feature/galileo-host-observability' into test-end-to-end-1
namrataghadi-galileo May 20, 2026
740bc0d
Merge branch 'feature/control-clone-and-bind' into test-end-to-end-1
namrataghadi-galileo May 20, 2026
da8f2da
fix(server): skip target auth without attachment context
namrataghadi-galileo May 21, 2026
2c1b488
Merge branch 'main' into feature/64546-add-new-luna-client
namrataghadi-galileo May 22, 2026
18fe79f
feat(server): add control clone-and-bind endpoint
abhinav-galileo May 19, 2026
58d9e14
fix(server): bound control attachment expansion
abhinav-galileo May 22, 2026
f513dac
address comments
namrataghadi-galileo May 22, 2026
c82de28
Merge branch 'feature/control-clone-and-bind' into feature/64546-add-…
namrataghadi-galileo May 22, 2026
7853b3b
merging from main
namrataghadi-galileo May 22, 2026
02813c6
mergeing from feature/control-clone-and-bind
namrataghadi-galileo May 22, 2026
d5cc751
Merge branch 'feature/64546-add-new-luna-client' into test-end-to-end-1
namrataghadi-galileo May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 127 additions & 1 deletion engine/src/agent_control_engine/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,108 @@
# Max concurrent evaluations (limits task spawning overhead for large policies)
MAX_CONCURRENT_EVALUATIONS = int(os.environ.get("MAX_CONCURRENT_EVALUATIONS", "3"))

SELECTED_DATA_PREVIEW_MAX_CHARS = int(
os.environ.get("AGENT_CONTROL_SELECTED_DATA_PREVIEW_MAX_CHARS", "500")
)
SELECTED_DATA_PREVIEW_MAX_ITEMS = int(
os.environ.get("AGENT_CONTROL_SELECTED_DATA_PREVIEW_MAX_ITEMS", "20")
)
SELECTED_DATA_PREVIEW_MAX_DEPTH = int(
os.environ.get("AGENT_CONTROL_SELECTED_DATA_PREVIEW_MAX_DEPTH", "3")
)
_SENSITIVE_KEY_PARTS = (
"api_key",
"apikey",
"authorization",
"credential",
"password",
"secret",
"token",
)


def _env_flag(name: str, *, default: bool = False) -> bool:
"""Read a boolean environment flag."""
value = os.environ.get(name)
if value is None:
return default
return value.strip().lower() in {"1", "true", "yes", "on"}


def _is_sensitive_key(key: object) -> bool:
"""Return whether a mapping key is likely to contain a secret."""
normalized = str(key).lower()
return any(part in normalized for part in _SENSITIVE_KEY_PARTS)


def _truncate_string(value: str, max_chars: int) -> tuple[str, bool]:
"""Return a bounded string preview and whether it was truncated."""
if len(value) <= max_chars:
return value, False
if max_chars <= 3:
return value[:max_chars], True
return f"{value[: max_chars - 3]}...", True


def _selected_data_preview_value(
value: Any,
*,
depth: int = 0,
) -> tuple[Any, bool]:
"""Build a bounded, redacted preview of selected data."""
if depth >= SELECTED_DATA_PREVIEW_MAX_DEPTH:
return "<max depth reached>", True

if value is None or isinstance(value, bool | int | float):
return value, False

if isinstance(value, str):
return _truncate_string(value, SELECTED_DATA_PREVIEW_MAX_CHARS)

if isinstance(value, dict):
preview: dict[str, Any] = {}
truncated = len(value) > SELECTED_DATA_PREVIEW_MAX_ITEMS
for index, (key, item) in enumerate(value.items()):
if index >= SELECTED_DATA_PREVIEW_MAX_ITEMS:
break
preview_key = str(key)
if _is_sensitive_key(key):
preview[preview_key] = "<redacted>"
truncated = True
continue
preview_item, item_truncated = _selected_data_preview_value(
item,
depth=depth + 1,
)
preview[preview_key] = preview_item
truncated = truncated or item_truncated
return preview, truncated

if isinstance(value, list | tuple):
preview_items: list[Any] = []
truncated = len(value) > SELECTED_DATA_PREVIEW_MAX_ITEMS
for item in value[:SELECTED_DATA_PREVIEW_MAX_ITEMS]:
preview_item, item_truncated = _selected_data_preview_value(
item,
depth=depth + 1,
)
preview_items.append(preview_item)
truncated = truncated or item_truncated
return preview_items, truncated

text_preview, truncated = _truncate_string(str(value), SELECTED_DATA_PREVIEW_MAX_CHARS)
return text_preview, truncated


def _selected_data_preview(value: Any) -> dict[str, Any]:
"""Return UI-safe selector output details for evaluator-level inspection."""
preview, truncated = _selected_data_preview_value(value)
return {
"type": type(value).__name__,
"value": preview,
"truncated": truncated,
}


@functools.lru_cache(maxsize=256)
def _compile_regex(pattern: str) -> Any:
Expand Down Expand Up @@ -102,9 +204,16 @@ def __init__(
self,
controls: Sequence[ControlWithIdentity],
context: Literal["sdk", "server"] = "server",
*,
include_raw_selected_data: bool | None = None,
):
self.controls = controls
self.context = context
self.include_raw_selected_data = (
_env_flag("AGENT_CONTROL_INCLUDE_RAW_SELECTED_DATA")
if include_raw_selected_data is None
else include_raw_selected_data
)

@staticmethod
def _truncated_message(message: str | None) -> str | None:
Expand Down Expand Up @@ -224,6 +333,9 @@ async def _evaluate_leaf(
"message": self._truncated_message(result.message),
}
metadata = dict(result.metadata or {})
if self.include_raw_selected_data:
metadata["engine_selected_data"] = data
metadata["engine_selected_data_preview"] = _selected_data_preview(data)
metadata["condition_trace"] = trace
return _ConditionEvaluation(
result=result.model_copy(update={"metadata": metadata}),
Expand Down Expand Up @@ -269,7 +381,21 @@ def _composite_metadata(
*,
matched: bool,
) -> dict[str, Any] | None:
"""Select stable child metadata to preserve on composite results."""
"""Select stable child metadata to preserve on composite results.

The engine_selected_data_preview value in this metadata is not all
evaluator inputs. It is the bounded selected value preview from the leaf
metadata the engine preserves for the final composite result:
- or where one child matches: engine_selected_data_preview comes from the
matching child.
- and where one child fails: engine_selected_data_preview comes from the
failing child.
- and where all children match: engine_selected_data_preview comes from the
first matching child, usually the first leaf.
- or where no children match: engine_selected_data_preview comes from the
first evaluated child.
- not: engine_selected_data_preview comes from its child.
"""
source_result: EvaluatorResult | None = None
if matched:
source_result = next(
Expand Down
Loading
Loading