Skip to content

PyAI Trace for GPT-Live

Compliance monitoring
for GPT-Live.

Customer conversations contain sensitive details. Add post-call PII review and transcript redaction to your GPT-Live recordings, while keeping your voice stack.

Post-call sensitive-data review · Trace beta

TRACE / RECORDING REVIEW

A sensitive detail.
A cleaner record.

PII detected

“Where should we send it?”

“Please send the annual pricing to [REDACTED_EMAIL]. Friday works for our review.”

Detected category
Email address
Review path
Hear + Trace
Scope
Transcript PII

Illustrative example. Actual findings depend on the recording, transcription and enabled scan. Redaction applies to the transcript, not the source audio.

From conversation to review

Give sensitive information somewhere to be caught.

01

Find supported PII

Scan the final transcript for supported identifiers and contact details, including card numbers, SSNs, emails and US phone numbers.

02

Work with a redacted transcript

Use the redacted result in the downstream review workflow you build. Keep source recordings and their access controls separate.

03

Keep the scope visible

Read the scan summary alongside the transcription result. A successful job and a clean PII scan answer different questions.

The supported setup

Keep GPT-Live.
Add review after the call.

Your application connects the recording to PyAI. No change to GPT-Live’s conversation model or delegated backend is required for this post-call path.

01

Obtain the completed recording

Use a finalized GPT-Live stored recording when available, or the recording from your own audio system. Capture both sides and apply your recording permissions.

02

Submit to Hear with Trace

Enable the required Trace entitlement. Prepare a compatible recording and submit it with trace: true. The single-job PII path does not support channel separation or diarization.

03

Read and route the result

Wait for the transcription job to complete or handle its completion webhook. Read its redacted transcript and Trace summary, then route them into your review process.

Managed sync, with one import request.

Connect an OpenAI project key once through PyAI’s owner/admin management API. Your backend then sends the completed session ID using its PyAI key. PyAI fetches the recording and returns a normal transcription job for polling or a signed completion webhook.

Implementation preview: the managed connector is built in development and disabled by default. It is not enabled on the public API yet. A live GPT-Live import canary is still required before rollout.
Managed import · after deployment and enablement
curl https://api.pyai.com/v1/transcription/jobs \
  -H "Authorization: Bearer $PYAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "gpt_live": { "session_id": "YOUR_COMPLETED_SESSION_ID" },
    "trace": true,
    "numerals": true
  }'

The one-time connection uses PUT /projects/{id}/integrations/gpt-live with an authenticated owner/admin session. Repeating a session import returns the same job; conflicting options are rejected. Your app must notify PyAI after each stored recording is finalized. This does not discover every session in an OpenAI account.

Run the standalone recording example.

This server-side Node.js 22+ example downloads the real stored recording, uploads it to Hear with Trace, and saves the scanned transcript and Trace summary to a local JSON file. No public recording URL or npm packages are needed.

  1. Enable recording storage in your OpenAI project and set store: true in the session configuration when you create the GPT-Live session. Save the session ID.
  2. Close the session with session.close, wait for session.closed, and allow the recording to finalize. Stored recordings are unavailable with Zero Data Retention and expire after 30 days.
  3. Use a PyAI key authorized for async transcription and an organization with Trace enabled. Set OPENAI_API_KEY, PYAI_API_KEY and GPT_LIVE_SESSION_ID on your server.
Run · Node.js 22+
# Set OPENAI_API_KEY, PYAI_API_KEY and GPT_LIVE_SESSION_ID
# in your server environment, then run the downloaded file:
node gpt-live-trace.mjs

Download gpt-live-trace.mjs ↓

View and copy the complete script
gpt-live-trace.mjs · complete runnable example
// Node.js 22+. Server-side only. No npm dependencies.
// Start GPT-Live with store: true; wait for session.closed and recording finalization.
import { writeFile } from "node:fs/promises";
import { pathToFileURL } from "node:url";
import { setTimeout as sleep } from "node:timers/promises";

export async function run(env = process.env, { request = fetch, pause = sleep } = {}) {
  const required = (name) => {
    if (!env[name]) throw new Error(`Set ${name} on your server.`);
    return env[name];
  };
  const auth = { Authorization: `Bearer ${required("PYAI_API_KEY")}` };
  const jobs = "https://api.pyai.com/v1/transcription/jobs";
  async function checked(url, options = {}) {
    const response = await request(url, {
      ...options, redirect: "error", signal: AbortSignal.timeout(120_000),
    });
    if (!response.ok) {
      // Do not log provider response bodies, credentials or signed URLs.
      throw new Error(`HTTP ${response.status} from ${new URL(url).host}. Check access, entitlement and recording readiness.`);
    }
    return response;
  }

  // Resume an existing job after a polling interruption instead of paying twice.
  let jobId = env.PYAI_JOB_ID;
  if (!jobId) {
    const sessionId = required("GPT_LIVE_SESSION_ID");
    const recording = await checked(
      `https://api.openai.com/v1/live/sessions/${encodeURIComponent(sessionId)}/content`,
      { headers: { Authorization: `Bearer ${required("OPENAI_API_KEY")}` } },
    );
    // Bound memory for this example. Stream large recordings in your production worker.
    const chunks = [];
    let bytes = 0;
    for await (const chunk of recording.body) {
      bytes += chunk.length;
      if (bytes > 64 * 1024 * 1024) throw new Error("Example limit: 64 MiB recording.");
      chunks.push(chunk);
    }
    if (!bytes) throw new Error("The stored recording is empty.");
    const form = new FormData();
    form.set("audio", new Blob(chunks, { type: "audio/wav" }), "gpt-live.wav");
    form.set("trace", "true");
    form.set("numerals", "true");
    // Hear mixes both channels for this path. Do not set channel or diarize.
    // fetch supplies the multipart boundary; do not set Content-Type yourself.
    // This multipart POST has no documented idempotency support: never auto-retry it.
    const created = await (await checked(jobs, { method: "POST", headers: auth, body: form })).json();
    jobId = created.job_id;
    if (typeof jobId !== "string" || !jobId) throw new Error("Missing job_id.");
    console.log(`Submitted ${jobId}. To resume, set PYAI_JOB_ID=${jobId}.`);
  }

  for (let attempt = 0; attempt < 450; attempt++) {
    const job = await (await checked(`${jobs}/${encodeURIComponent(jobId)}`, { headers: auth })).json();
    if (job.status === "failed" || job.status === "cancelled") {
      throw new Error(`Job ${jobId} ${job.status}. Inspect its error in your secured backend.`);
    }
    if (job.status === "completed") {
      let result = job.result;
      if (!result && job.result_url) {
        const url = new URL(job.result_url);
        if (url.protocol !== "https:" || url.username || url.password) throw new Error("Invalid result URL.");
        // A signed storage URL needs no API key. Never forward either provider's key.
        result = await (await checked(url.href)).json();
      }
      if (typeof result?.text !== "string" || !result.trace ||
          typeof result.trace.verdict !== "string" ||
          !Number.isInteger(result.trace.n_pii) || result.trace.n_pii < 0 ||
          typeof result.trace.redacted !== "boolean") {
        throw new Error("Completed job is missing a valid Trace result.");
      }
      return { job_id: jobId, ...result };
    }
    if (!["queued", "running"].includes(job.status)) throw new Error("Unknown job status.");
    await pause(2_000);
  }
  throw new Error(`Polling limit reached. Resume with PYAI_JOB_ID=${jobId}; do not resubmit.`);
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  try {
    const result = await run();
    const output = `trace-result-${Date.now()}.json`;
    await writeFile(output, JSON.stringify(result, null, 2), { mode: 0o600, flag: "wx" });
    console.log(`Saved ${output}. PII matches: ${result.trace.n_pii}.`);
    // result.text is the scanned transcript; result.trace holds verdict/n_pii/redacted.
    // Review coverage: unmatched sensitive data can remain; source audio is not redacted.
  } catch (error) {
    console.error(error.message);
    process.exitCode = 1;
  }
}

Reads result.text and result.trace, including results returned through a signed download URL. Both audio channels are mixed for this scan; speaker attribution is not retained. The example limits recordings to 64 MiB and keeps API keys on your server. It redacts supported matches in the transcript, not the source audio.

If polling stops, set PYAI_JOB_ID to the printed job ID and rerun to resume. If the initial upload fails without returning an ID, check your jobs before resubmitting: multipart uploads do not support idempotent retries. Hear and Trace usage are billed; uploaded audio may be retained for up to 7 days and results for 30 days under the current API policy.

Validation: checked against the current API contracts and automated mocked responses. A live GPT-Live → Trace run has not yet been verified. OpenAI recording setup · Trace setup guide.

Know exactly what you are adding

PII review, with clear boundaries.

Included in this path

  • Async recording transcription through Hear
  • Supported deterministic PII checks
  • Transcript redaction and a Trace summary
  • Explicit processing on eligible jobs

Requires a different setup

  • Full rule-pack scorecards and semantic findings
  • Live speech blocking or intervention
  • Speaker attribution in the same scanning job
  • Proof of playback, consent or completed actions
Need full call QA for a GPT-Live deployment? Talk through your call path with us so the available inputs, checks and outputs match what your team needs.

Make the rest of the call useful

Pair review with a useful handoff.

Recap turns speaker-labelled conversations into summaries, action items and structured fields. Validate the inputs for each path when combining it with Trace.

See Recap for GPT-Live →

Before you build

Good questions. Clear answers.

Does Trace make GPT-Live HIPAA compliant?

No. This recording-based integration detects supported PII patterns and redacts the resulting transcript. It does not establish HIPAA compliance or include the full HIPAA rule pack on this path. Broader Trace coverage requires a supported, explicitly enabled call path.

Can I use PyAI Trace with GPT-Live?

Yes, through the documented recording-based Hear + Trace path. Your application obtains the call recording, prepares a compatible audio input and submits an async transcription job with trace enabled. This is an application-level integration, not a native GPT-Live connector.

What does this integration scan?

The async recording path performs deterministic PII scanning and transcript redaction for supported patterns: SSNs, credit-card numbers, CVV in context, email addresses and US phone numbers. It returns a Trace summary with the transcription result. Detection depends on transcript quality and supported patterns.

Does this include every Trace rule pack?

No. The external recording path described here covers deterministic PII scanning. Full rule-pack scorecards, semantic findings and audit hashes are available on other eligible Trace-enabled paths; do not assume they are produced for an arbitrary GPT-Live recording.

Does Trace block GPT-Live speech or business actions?

This path reviews the completed recording. It does not intercept GPT-Live playback or block its backend tools. Keep live permissions, consent handling and action controls in your application.

Can I retain separate speakers while scanning?

The documented trace option cannot be combined with channel or diarize in the same Hear job. Keep the original recording and speaker-labelled transcript separately. If your workflow needs both speaker attribution and PII review, validate separate processing paths before launch.

Is a clean scan a compliance guarantee?

No. A scan reports what the configured checks found in the supplied transcript. It does not establish legal compliance, prove a disclosure was heard or certify that the recording contains no sensitive information.

How is it enabled and billed?

Trace is in beta. The recording path requires the organization's Trace entitlement and an explicit trace option on the transcription job. Hear processing and Trace usage are metered separately. Check PyAI pricing and your console for current terms.

Documentation / reviewed September 11, 2026

Independent PyAI integration guidance. No OpenAI partnership or native connector is implied.

Start with the calls you need to review.

Bring your recording format and review requirements. We’ll help you identify the supported Trace path.