Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 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
6 changes: 5 additions & 1 deletion .github/workflows/agentex-tutorials-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:

jobs:
find-tutorials:
# Repo guard: this workflow is specific to the production repo. Staging carries the
# same file (the trunks are kept SHA-identical) but has none of its secrets, so
# without this it runs and fails red on every codegen push.
if: github.repository == 'scaleapi/scale-agentex-python'
runs-on: ubuntu-latest
outputs:
tutorials: ${{ steps.get-tutorials.outputs.tutorials }}
Expand Down Expand Up @@ -235,7 +239,7 @@ jobs:
retention-days: 1

test-summary:
if: always()
if: always() && github.repository == 'scaleapi/scale-agentex-python'
needs: [find-tutorials, test-tutorial]
runs-on: ubuntu-latest
name: Test Summary
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/bandit-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Bandit

on:
# Scan changed files in PRs:
pull_request: {}

jobs:
bandit-scan:
name: Bandit
runs-on: ubuntu-22.04
if: (github.actor != 'dependabot[bot]') && (github.actor != 'github-actions[bot]')
steps:
- name: Install PyCQA/bandit
shell: bash
run: |
pip install bandit
- name: Checkout base branch
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.base.ref }}
fetch-depth: 1
submodules: false
- name: Run a baseline scan
shell: bash
run: |
bandit --recursive --aggregate file . -f json -o baseline.json || true
- name: Checkout feature branch
shell: bash
run: |
git fetch origin $GITHUB_HEAD_REF
git checkout $GITHUB_HEAD_REF
- name: Run Scan off of baseline
shell: bash
run: |
bandit --recursive --aggregate file . --baseline baseline.json -f json -o results.json || true
- name: Install logging prerequisites
shell: bash {0}
run: |
sudo apt-get -y install jq curl
- name: Generate logger template
shell: bash {0} # don't fail the job if the logging fails
run: |
jq -n --arg organization $GITHUB_REPOSITORY_OWNER \
-n --arg time $( date +'%Y-%m-%dT%H:%M:%SZ' ) \
-n --arg action $GITHUB_WORKFLOW \
-n --arg repository $GITHUB_REPOSITORY \
-n --arg sha $GITHUB_SHA \
-n --arg branch $GITHUB_HEAD_REF \
-n --arg link "https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
-f .github/workflows/output-template.json > tmp-output.json
- name: Format results appropriately from results.json
shell: bash {0} # don't fail the job if the logging fails
run: |
jq '.results | map({"path": .filename, "message": .issue_text, "line": .line_number})' results.json > tmp.json
# --slurpfile, not --argjson "$(<tmp.json)": the latter passes the whole results file
# as a single argv entry, which Linux caps at MAX_ARG_STRLEN (128KB) regardless of the
# much larger total ARG_MAX. Once a scan produced more than ~128KB of findings the step
# died with "Argument list too long" (exit 126) and failed the job -- despite the
# `shell: bash {0}` above intending it to be non-fatal. --slurpfile reads the file
# directly, so size is irrelevant; it wraps the file's values in an array, hence [0].
jq --slurpfile scanResults tmp.json '.results += $scanResults[0]' tmp-output.json > output.json
- name: Send unified results to logging cluster
shell: bash {0} # don't fail the job if the logging fails
run: |
curl -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.N8N_PRODSEC_ACTIONS_TOKEN }}" \
-d @./output.json \
${{ secrets.N8N_PRODSEC_ACTIONS_ENDPOINT }}
4 changes: 4 additions & 0 deletions .github/workflows/build-and-push-tutorial-agent.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ permissions:

jobs:
check-permissions:
# Repo guard: this workflow is specific to the production repo. Staging carries the
# same file (the trunks are kept SHA-identical) but has none of its secrets, so
# without this it runs and fails red on every codegen push.
if: github.repository == 'scaleapi/scale-agentex-python'
runs-on: ubuntu-latest
steps:
- name: Check event type and permissions
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/harness-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ on:

jobs:
conformance:
# Repo guard: this workflow is specific to the production repo. Staging carries the
# same file (the trunks are kept SHA-identical) but has none of its secrets, so
# without this it runs and fails red on every codegen push.
if: github.repository == 'scaleapi/scale-agentex-python'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
Expand All @@ -38,6 +42,10 @@ jobs:
# trigger above uses a `test_harness_*.py` glob so new suites are picked up
# automatically.
live-matrix:
# Repo guard: this workflow is specific to the production repo. Staging carries the
# same file (the trunks are kept SHA-identical) but has none of its secrets, so
# without this it runs and fails red on every codegen push.
if: github.repository == 'scaleapi/scale-agentex-python'
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/lint-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,17 @@ jobs:
# These bots may not always emit Conventional-Commits-formatted titles
# (dependabot's default "Bump foo from 1.0 to 1.1" doesn't match) and we
# don't want their PRs blocked by this check. Mirrors validate-pr-base.
#
# agentex-sdk-sync[bot] is this repo's own SDK automation. release-please
# runs here as a CLI under that App rather than as the release-please[bot]
# GitHub App, so its release pull requests are authored by
# agentex-sdk-sync[bot] and the entry above never matched them. Their
# titles come from release-please's configured pull-request-title-pattern,
# "release: <version>", which is not a Conventional Commits type and cannot
# be changed without also changing the string release-please parses back
# when it cuts the release. The same App opens the promote pull requests.
case "$PR_AUTHOR" in
stainless-app|stainless-app\[bot\]|release-please\[bot\]|github-actions\[bot\]|dependabot\[bot\])
stainless-app|stainless-app\[bot\]|release-please\[bot\]|github-actions\[bot\]|dependabot\[bot\]|agentex-sdk-sync\[bot\])
echo "PR is from automation ($PR_AUTHOR); skipping title check."
exit 0
;;
Expand Down Expand Up @@ -93,7 +102,7 @@ jobs:

# Exempt automated PRs (must mirror validate-pr-title's list).
case "$PR_AUTHOR" in
stainless-app|stainless-app\[bot\]|release-please\[bot\]|github-actions\[bot\]|dependabot\[bot\])
stainless-app|stainless-app\[bot\]|release-please\[bot\]|github-actions\[bot\]|dependabot\[bot\]|agentex-sdk-sync\[bot\])
delete_comment
echo "PR is from automation ($PR_AUTHOR); allowing PR targeting main."
exit 0
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/opengrep-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: OpenGrep

on:
pull_request: {}

concurrency:
group: opengrep-${{ github.event.pull_request.number }}
cancel-in-progress: true

permissions:
contents: read
pull-requests: write
id-token: write

jobs:
opengrep:
uses: scaleapi/required-actions/.github/workflows/opengrep-ci.yml@opengrep-4core-runner
secrets: inherit
Comment on lines +17 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 This job loads executable workflow code from a branch name and gives it every available caller secret. Anyone who can move that branch, or an attacker who compromises it, can read repository secrets and use the job's write and OIDC permissions. Pin the reusable workflow to a reviewed commit SHA and pass only named secrets.

How this was verified: The same job uses a mutable @opengrep-4core-runner ref and secrets: inherit.

Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/opengrep-ci.yml
Line: 17-18

Comment:
This job loads executable workflow code from a branch name and gives it every available caller secret. Anyone who can move that branch, or an attacker who compromises it, can read repository secrets and use the job's write and OIDC permissions. Pin the reusable workflow to a reviewed commit SHA and pass only named secrets.

**How this was verified:** The same job uses a mutable `@opengrep-4core-runner` ref and `secrets: inherit`.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Cursor Fix in Claude Code Fix in Codex

18 changes: 18 additions & 0 deletions .github/workflows/opengrep-fp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: OpenGrep FP Triage

on:
pull_request_review_comment:
types: [created]

permissions:
pull-requests: write
id-token: write

jobs:
triage:
if: |
(startsWith(github.event.comment.body, '/fp') ||
startsWith(github.event.comment.body, '/FP')) &&
!endsWith(github.actor, '[bot]')
uses: scaleapi/required-actions/.github/workflows/opengrep-fp.yml@main
secrets: inherit
4 changes: 4 additions & 0 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ on:

jobs:
publish:
# Repo guard: this workflow is specific to the production repo. Staging carries the
# same file (the trunks are kept SHA-identical) but has none of its secrets, so
# without this it runs and fails red on every codegen push.
if: github.repository == 'scaleapi/scale-agentex-python'
name: publish
runs-on: ubuntu-latest

Expand Down
80 changes: 80 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Release Please

# Hand-edited from the stlc-generated template. `.github/workflows/*.yml` is
# scaffold-once, so this survives every later build -- upstream's own source cites
# exactly this PAT-to-App swap as the reason that preservation exists. Do NOT run
# `stlc build --rewrite-scaffold` without reapplying these three changes.
#
# What changed from the generated file, and why each is load-bearing:
#
# 1. App token instead of `secrets.RELEASE_PLEASE_TOKEN`, which does not exist
# and which we do not want to create -- eliminating PATs was the point of the
# App migration. It is deliberately NOT `GITHUB_TOKEN`: releases created by
# GITHUB_TOKEN do not trigger other workflows, so publish-*.yml would never
# fire and the release would stop one hop short of the registry.
#
# 2. The `npx release-please@16` CLI instead of googleapis/release-please-action.
# scale-agentex-typescript sets `allowed_actions: selected` and does not permit
# that action; the CLI needs only actions/-owned steps, which
# `github_owned_allowed: true` covers on both production repos.
#
# 3. `issues: write` on the minted token. release-please drives its
# autorelease:pending -> autorelease:tagged labels through the Issues API.
# Without it you get duplicate release pull requests. The generated file omits
# it, and the omission is silent until it bites.
#
# Requires AGENTEX_SDK_SYNC_PRIVATE_KEY (secret) and AGENTEX_SDK_SYNC_APP_ID
# (variable) on the PRODUCTION repo -- a workflow only reads secrets from the repo
# it runs in, and the guard below means that is production.
on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

jobs:
release-please:
# Self-routing: this file is SHA-identical on the staging trunk, where it must
# stay inert. Only production cuts releases.
if: github.repository == 'scaleapi/scale-agentex-python'
runs-on: ubuntu-latest
steps:
- name: Mint release token
id: release-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.AGENTEX_SDK_SYNC_APP_ID }}
private-key: ${{ secrets.AGENTEX_SDK_SYNC_PRIVATE_KEY }}
owner: scaleapi
repositories: scale-agentex-python
permission-contents: write
permission-pull-requests: write
permission-issues: write
permission-metadata: read

- uses: actions/setup-node@v4
with:
node-version: '20'

- name: Release PR + GitHub release
env:
RP_TOKEN: ${{ steps.release-token.outputs.token }}
run: |
# release-pr opens or updates the version-bump pull request;
# github-release turns an already-merged one into the tag + GitHub Release
# that publish-pypi.yml / publish-npm.yml trigger on. Both are idempotent,
# so running the pair on every push carries a release the whole way.
#
# No checkout step is needed: release-please reads the config and manifest
# from the repo over the API.
npx --yes release-please@16 release-pr \
--token="$RP_TOKEN" --repo-url="${{ github.repository }}" \
--config-file=release-please-config.json \
--manifest-file=.release-please-manifest.json
npx --yes release-please@16 github-release \
--token="$RP_TOKEN" --repo-url="${{ github.repository }}" \
--config-file=release-please-config.json \
--manifest-file=.release-please-manifest.json
16 changes: 16 additions & 0 deletions .github/workflows/trufflehog-bypass.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
name: TruffleHog Bypass Handler

on:
issue_comment:
types: [created]

jobs:
bypass:
if: |
github.event.issue.pull_request &&
contains(github.event.comment.body, '/trufflehog-bypass')
uses: scaleapi/required-actions/.github/workflows/trufflehog-bypass-handler.yml@main
permissions:
pull-requests: write
contents: read
actions: write
13 changes: 13 additions & 0 deletions .github/workflows/trufflehog-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: TruffleHog Secret Scan

on:
pull_request:
branches: [master, main]

jobs:
scan:
uses: scaleapi/required-actions/.github/workflows/trufflehog-scan.yml@main
permissions:
contents: read
pull-requests: write
id-token: write
26 changes: 26 additions & 0 deletions .github/workflows/trufflehog-weekly.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: TruffleHog Weekly Scan

on:
schedule:
- cron: '0 3 * * 0'
workflow_dispatch:
inputs:
since_commit:
description: 'Override: Scan from this commit SHA (leave empty to use stored value)'
required: false
type: string
full_scan:
description: 'Run full history scan (ignores since_commit)'
required: false
type: boolean
default: false

jobs:
scan:
uses: scaleapi/required-actions/.github/workflows/trufflehog-weekly-scan.yml@main
with:
since_commit: ${{ inputs.since_commit || '' }}
full_scan: ${{ inputs.full_scan || false }}
permissions:
contents: read
id-token: write
3 changes: 0 additions & 3 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
configured_endpoints: 75
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/sgp/agentex-sdk-fbc0683871d6abb03588f30d9468eeeeacb2b8538eb0c9002813e6df68c5802b.yml
openapi_spec_hash: 4ecd8d496f056dccf80826264ddf8fe1
config_hash: 593e89b291976a5e84e4c3c3f8324354
20 changes: 0 additions & 20 deletions adk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,6 @@ This automatically pulls in [`agentex-client`](../) (the slim Stainless-generate

The two packages contribute disjoint files to the `agentex.*` namespace — `agentex/lib/*` ships only from `agentex-sdk`.

## Workflow logging

Use the workflow logger in Temporal workflow code:

```python
from agentex.lib.core.temporal.logging import make_workflow_logger

logger = make_workflow_logger(__name__)
```

It suppresses logs while Temporal replays recorded history and adds top-level
`workflow_id` and `run_id` fields during workflow execution. It preserves the
message, caller fields, and exception details. Outside workflows, including in
activities, it behaves like the ordinary SDK logger.

New Temporal templates use this helper. Existing agents must replace their own
workflow loggers to get the same behavior. This does not create trace context or
add trace IDs to workflows that lack it. Temporal's worker diagnostics still report
replay failures.

## Repo layout

This package is hand-authored and lives at `adk/` inside [scaleapi/scale-agentex-python](https://github.com/scaleapi/scale-agentex-python). Stainless codegen never touches `adk/**` — it's outside the generated surface. The sibling `agentex-client` package lives at the repo root and IS Stainless-generated.
Expand Down
Loading
Loading