Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
602 changes: 602 additions & 0 deletions agents/explore.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions docs/explore.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Explore Agent

Inspects a work item (GitHub issue or Jira ticket), gathers technical context from the target codebase, referenced repos, related work, and public web sources, then produces a structured exploration result for downstream agents.

## How the agent works

The explore agent runs after a work item enters the refinement pipeline. A host pre-script fetches issue context and optionally shallow-clones public GitHub repos referenced in the issue. The agent researches inside a sandbox with read-only GitHub/Jira/web access, writes a schema-validated JSON result, and a post-script attaches the result, posts a sticky summary comment, and optionally applies pipeline labels.

Host pre-script uses runner credentials to fetch issue context and shallow-clone
public repos. The sandbox receives `GH_TOKEN` / Jira env via the harness for
read API fallbacks, constrained by OpenShell network policy (github.com,
api.github.com, configured Jira host). Prefer pre-cloned trees so the agent
rarely needs live git.

## How it helps

- Downstream agents receive structured technical landscape, related work, and definition gaps instead of raw issue text.
- Referenced repos are pre-cloned so the agent can grep and inspect code without live git clones in the sandbox.
- Confidence scoring and optional pipeline labels signal when a work item is ready for the next stage.

## Platform support

| Source | Pre-script | Post-script |
|--------|------------|-------------|
| GitHub | `gh issue view`, sub-issues | Sticky comment via `fullsend post-comment`, optional labels |
| Jira | REST API + ADF conversion, hierarchy | Attachment + sticky ADF comment, optional labels |

Set `ISSUE_SOURCE` to `jira` or `github`. The agent prompt also accepts `text` and `web` as input source values in the output JSON when the work item did not originate from a tracker.

## Optional pipeline labels

Labels are opt-in via runner env vars — the generic agent does not hardcode team-specific label names:

| Env var | Purpose |
|---------|---------|
| `EXPLORE_READY_LABEL` | Applied when confidence ≥ threshold |
| `EXPLORE_NEEDS_INFO_LABEL` | Applied when confidence < threshold |
| `EXPLORE_CONFIDENCE_THRESHOLD` | Minimum confidence for ready label (default: 2.5, scale 0–5) |

GitHub labels must already exist in the repo; the post-script will not auto-create them.

## Configuration and extension

Register the agent via harness `base:` composition. Downstream configs (e.g. team refinement hubs) add skills and env overrides:

```yaml
base: https://raw.githubusercontent.com/fullsend-ai/agents/main/harness/explore.yaml
skills:
- skills/jira-routing # team-specific
env:
runner:
EXPLORE_READY_LABEL: ready-to-refine

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] (non-blocking) The example label ready-to-refine bakes in a pipeline-specific name. Since the docs emphasize labels are generic and opt-in, something like explore-complete would reinforce that.

EXPLORE_NEEDS_INFO_LABEL: needs-info
```

Built-in skills: `public-research`, `jira-read`.

## Output

The agent writes `agent-result.json` validated against `schemas/explore-result.schema.json`. The post-script copies it to `exploration_context.json` and attaches it to Jira issues for re-runs.
4 changes: 4 additions & 0 deletions env/explore.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export ISSUE_CONTEXT=/tmp/workspace/issue-context.json
export FULLSEND_OUTPUT_DIR=/sandbox/workspace/output
export REFERENCED_REPOS_DIR=/sandbox/workspace/referenced-repos
export ORG_KNOWLEDGE=/sandbox/workspace/org-knowledge.md
60 changes: 60 additions & 0 deletions harness/explore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
doc: docs/explore.md
agent: agents/explore.md
model: opus
image: ghcr.io/fullsend-ai/fullsend-sandbox:latest
policy: policies/explore.yaml

role: explore
slug: fullsend-ai-explore

host_files:
- src: common/env/gcp-vertex.env
dest: /sandbox/workspace/.env.d/gcp-vertex.env
expand: true
- src: env/explore.env
dest: /sandbox/workspace/.env.d/explore.env
expand: true
- src: ${GOOGLE_APPLICATION_CREDENTIALS}
dest: /tmp/.gcp-credentials.json
- src: ${GCP_OIDC_TOKEN_FILE}
dest: /sandbox/workspace/.gcp-oidc-token
optional: true

skills:
- skills/public-research
- skills/jira-read

pre_script: scripts/pre-explore.sh
post_script: scripts/post-explore.sh

validation_loop:
script: scripts/validate-output-schema.sh
schema: schemas/explore-result.schema.json
max_iterations: 2

env:
runner:
ISSUE_KEY: ${ISSUE_KEY}
ISSUE_SOURCE: ${ISSUE_SOURCE}
REPO_FULL_NAME: ${REPO_FULL_NAME}
GITHUB_ISSUE_NUMBER: ${GITHUB_ISSUE_NUMBER}
GH_TOKEN: ${GH_TOKEN}
JIRA_HOST: ${JIRA_HOST}
JIRA_EMAIL: ${JIRA_EMAIL}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] secret-exposure

The harness passes JIRA_EMAIL, JIRA_HOST, and JIRA_API_TOKEN into the sandbox (env.sandbox). docs/explore.md states 'Credentials stay on the runner — they never enter the sandbox' which is a factual contradiction.

Suggested fix: Either remove JIRA_* credentials from env.sandbox or update docs/explore.md to accurately reflect that Jira credentials do enter the sandbox.

JIRA_API_TOKEN: ${JIRA_API_TOKEN}
EXPLORE_CONFIDENCE_THRESHOLD: ${EXPLORE_CONFIDENCE_THRESHOLD}
EXPLORE_READY_LABEL: ${EXPLORE_READY_LABEL}
EXPLORE_NEEDS_INFO_LABEL: ${EXPLORE_NEEDS_INFO_LABEL}
REFERENCED_REPOS_DIR: /sandbox/workspace/referenced-repos
FULLSEND_OUTPUT_SCHEMA: ${FULLSEND_DIR}/schemas/explore-result.schema.json
sandbox:
ISSUE_KEY: "${ISSUE_KEY}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] secret-exposure

The harness config passes JIRA_EMAIL, JIRA_HOST, and JIRA_API_TOKEN into the sandbox environment (env.sandbox block). docs/explore.md states 'Credentials stay on the runner -- they never enter the sandbox' which is a factual contradiction. The credentials are present inside the sandbox and the agent prompt instructs their use.

Suggested fix: Either remove JIRA_* credentials from env.sandbox and have the pre-script fetch all needed Jira data, or update docs/explore.md to accurately reflect that Jira credentials do enter the sandbox.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] secret-exposure

The harness config passes JIRA_EMAIL, JIRA_HOST, and JIRA_API_TOKEN into the sandbox environment (env.sandbox block). The docs/explore.md states 'Credentials stay on the runner — they never enter the sandbox' which is a factual contradiction. The agent prompt acknowledges the credentials are in-sandbox.

Suggested fix: Either remove JIRA credentials from env.sandbox and have the pre-script fetch all needed Jira data, or update docs/explore.md to accurately reflect that Jira credentials enter the sandbox.

ISSUE_SOURCE: "${ISSUE_SOURCE}"
REPO_FULL_NAME: "${REPO_FULL_NAME}"
# Read-only Jira lookups for related projects (KFLUXUI/STONEINTG/etc.).
JIRA_HOST: "${JIRA_HOST}"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] secret-exposure

The harness config passes JIRA_EMAIL, JIRA_HOST, and JIRA_API_TOKEN into the sandbox environment (env.sandbox block). docs/explore.md (line 9) states Credentials stay on the runner -- they never enter the sandbox which is a factual contradiction. The agent prompt correctly acknowledges the credentials are in-sandbox.

Suggested fix: Update docs/explore.md to accurately reflect that Jira credentials do enter the sandbox for read-only related-project lookups.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] secret-exposure

The harness config passes JIRA_EMAIL, JIRA_HOST, JIRA_API_TOKEN into the sandbox environment. docs/explore.md line 9 states Credentials stay on the runner which is a factual contradiction. The network policy enforces read-only access but the documentation is misleading.

Suggested fix: Update docs/explore.md to accurately reflect that Jira credentials enter the sandbox for read-only related-project lookups.

JIRA_EMAIL: "${JIRA_EMAIL}"
JIRA_API_TOKEN: "${JIRA_API_TOKEN}"

timeout_minutes: 20
82 changes: 82 additions & 0 deletions policies/explore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
version: 1

filesystem_policy:
include_workdir: true
read_only: [/usr, /lib, /proc, /dev/urandom, /app, /etc, /var/log]
read_write: [/sandbox, /tmp, /dev/null]
landlock:
compatibility: best_effort
process:
run_as_user: sandbox
run_as_group: sandbox

network_policies:
vertex_ai:
name: vertex-ai
endpoints:
- host: "api.anthropic.com"
port: 443
protocol: rest
enforcement: enforce
access: read-write
- host: "*.googleapis.com"
port: 443
protocol: rest
enforcement: enforce
access: read-write
binaries:
- path: "**/claude"
- path: "**/node"

github_api:
name: github-api
endpoints:
- host: "api.github.com"
port: 443

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[moderate] The explore agent is described as read-only, and the post-script handles all writes from the host. But this policy grants read-write to api.github.com from inside the sandbox. If the agent shouldn't mutate GitHub state, read-only would be more consistent with the stated constraints.

protocol: rest
enforcement: enforce
access: read-write
- host: "github.com"
port: 443
protocol: rest
enforcement: enforce
access: read-write
- host: "raw.githubusercontent.com"
port: 443
protocol: rest
enforcement: enforce
access: read-only
binaries:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] security

*.google.com wildcard allows connections to any Google subdomain including storage.googleapis.com which could be used for data exfiltration.

Suggested fix: Restrict to specific subdomains needed for search (e.g., www.google.com)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in db4947e. Replaced *.google.com wildcard with www.google.com in the web-search policy.

- path: "**/gh"
- path: "**/git"
- path: "**/node"
- path: "**/curl"

jira_api:
name: jira-api
endpoints:
- host: "*.atlassian.net"
port: 443
protocol: rest
enforcement: enforce
access: read-only
binaries:
- path: "**/curl"
- path: "**/node"

web_search:
name: web-search
endpoints:
- host: "api.tavily.com"
port: 443
protocol: rest
enforcement: enforce
access: read-write
- host: "www.google.com"
port: 443
protocol: rest
enforcement: enforce
access: read-only
binaries:
- path: "**/curl"
- path: "**/node"
Loading
Loading