coaiajs 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/agents/custom_gpt/ceremony-media-proxy.instructions.md +86 -0
- package/agents/custom_gpt/ceremony-media-proxy.yml +158 -0
- package/agents/custom_gpt/ceremony-observations.instructions.md +38 -5
- package/agents/custom_gpt/ceremony-observations.yml +737 -287
- package/dist/src/cli.js +2 -2
- package/dist/src/config.d.ts +2 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +10 -2
- package/dist/src/config.js.map +1 -1
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/langfuse/index.d.ts +2 -1
- package/dist/src/langfuse/index.d.ts.map +1 -1
- package/dist/src/langfuse/index.js +1 -1
- package/dist/src/langfuse/index.js.map +1 -1
- package/dist/src/langfuse/media.d.ts +30 -0
- package/dist/src/langfuse/media.d.ts.map +1 -1
- package/dist/src/langfuse/media.js +128 -77
- package/dist/src/langfuse/media.js.map +1 -1
- package/dist/src/media-upload-proxy.d.ts +32 -0
- package/dist/src/media-upload-proxy.d.ts.map +1 -0
- package/dist/src/media-upload-proxy.js +210 -0
- package/dist/src/media-upload-proxy.js.map +1 -0
- package/dist/src/redis.d.ts +10 -5
- package/dist/src/redis.d.ts.map +1 -1
- package/dist/src/redis.js +94 -8
- package/dist/src/redis.js.map +1 -1
- package/llms-full.txt +9 -1
- package/llms.txt +1 -0
- package/package.json +7 -2
- package/rispecs/03-langfuse-module.spec.md +2 -1
package/README.md
CHANGED
|
@@ -50,7 +50,8 @@ Import from the root, or from a subpath to pull in only what you need. Every ent
|
|
|
50
50
|
| `coaiajs/github` | `listIssues`, `getIssue`, `getIssueComments`, `resetClient` |
|
|
51
51
|
| `coaiajs/environment` | `EnvironmentManager`, `createEnvironment`, `findEnvironment` |
|
|
52
52
|
| `coaiajs/version` | `getPackageVersion` |
|
|
53
|
-
| `coaiajs/langfuse` | Langfuse JS SDK v5/OpenTelemetry tracing plus v4 observations, prompts, datasets, scores, comments, media, projects, and formatters (
|
|
53
|
+
| `coaiajs/langfuse` | Langfuse JS SDK v5/OpenTelemetry tracing plus v4 observations, prompts, datasets, scores, comments, media, projects, and formatters (56 runtime exports) |
|
|
54
|
+
| `coaiajs/media-upload-proxy` | Deployable Custom GPT conversation-file to Langfuse media bridge |
|
|
54
55
|
| `coaiajs/narrative` | `KnowledgeGraphManager`, chart operations, markdown export, tool definitions (29 exports) |
|
|
55
56
|
| `coaiajs/pde` | `SessionManager`, `StcMapper`, `handlePdeTool`, `PDE_MCP_TOOLS` (10 exports) |
|
|
56
57
|
| `coaiajs/planning` | `parsePlan`, `planToSTC`, `syncToChart`, `syncToPlan`, `handlePlanningTool` (10 exports) |
|
|
@@ -140,7 +141,9 @@ Migration references: [Langfuse v4](https://langfuse.com/docs/v4) · [versions a
|
|
|
140
141
|
|
|
141
142
|
### Custom GPT observation actions
|
|
142
143
|
|
|
143
|
-
[`agents/custom_gpt/ceremony-observations.yml`](./agents/custom_gpt/ceremony-observations.yml) is a focused OpenAPI 3.1 action specification for creating a root observation and appending child observations to the same Langfuse trace through OTLP/HTTP JSON. It contains
|
|
144
|
+
[`agents/custom_gpt/ceremony-observations.yml`](./agents/custom_gpt/ceremony-observations.yml) is a focused OpenAPI 3.1 action specification for creating a root observation and appending child observations to the same Langfuse trace through OTLP/HTTP JSON. It contains 23 core actions—below the 30-action limit—including media upload-record, retrieval, and finalization capabilities; destructive operations remain omitted. Media hashes use the required 44-character padded Base64 SHA-256 digest of the exact upload bytes, and the documented workflow distinguishes URL creation from the actual presigned PUT. Setup, authentication, ID/timestamp rules, and ready-to-paste GPT instructions are in [`ceremony-observations.instructions.md`](./agents/custom_gpt/ceremony-observations.instructions.md). The broader imported API surface remains available in [`ceremony.yml`](./agents/custom_gpt/ceremony.yml).
|
|
145
|
+
|
|
146
|
+
For autonomous conversation-file uploads, deploy the included `coaiajs-media-proxy` service and import [`ceremony-media-proxy.yml`](./agents/custom_gpt/ceremony-media-proxy.yml) as a second Action. It uses OpenAI's `openaiFileIdRefs` transfer, downloads the actual user/DALL-E/Code Interpreter file, performs the Langfuse media record + presigned PUT + finalization sequence, and returns a renderable `@@@langfuseMedia...@@@` token. Deployment and security instructions are in [`ceremony-media-proxy.instructions.md`](./agents/custom_gpt/ceremony-media-proxy.instructions.md). Together both specs expose 24 actions.
|
|
144
147
|
|
|
145
148
|
---
|
|
146
149
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Ceremony Media Upload Proxy
|
|
2
|
+
|
|
3
|
+
`ceremony-media-proxy.yml` is the executable bridge missing from direct Langfuse media actions. It uses the official Custom GPT `openaiFileIdRefs` mechanism, so the GPT sends a temporary reference to the user's real file instead of attempting to place a large Base64 payload in function arguments.
|
|
4
|
+
|
|
5
|
+
## Why this is a second action specification
|
|
6
|
+
|
|
7
|
+
The main `ceremony-observations.yml` talks directly to `cloud.langfuse.com`. A presigned media URL points to a dynamic object-storage host, which cannot be represented as a static OpenAPI path. The bridge therefore runs on a public HTTPS service you control and is imported as a second GPT Action. Together the specifications expose 24 actions, below the 30-action limit.
|
|
8
|
+
|
|
9
|
+
## Deploy the bridge
|
|
10
|
+
|
|
11
|
+
Build and run the included Node service:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install
|
|
15
|
+
npm run build
|
|
16
|
+
|
|
17
|
+
export LANGFUSE_PUBLIC_KEY='pk-lf-...'
|
|
18
|
+
export LANGFUSE_SECRET_KEY='sk-lf-...'
|
|
19
|
+
export LANGFUSE_BASE_URL='https://cloud.langfuse.com'
|
|
20
|
+
export COAIA_MEDIA_PROXY_API_KEY='generate-a-long-random-secret'
|
|
21
|
+
export PORT=8787
|
|
22
|
+
|
|
23
|
+
node dist/src/media-upload-proxy.js
|
|
24
|
+
# or, from the installed package:
|
|
25
|
+
coaiajs-media-proxy
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Deploy it behind a public HTTPS URL. The Custom GPT service cannot reach localhost.
|
|
29
|
+
|
|
30
|
+
Optional controls:
|
|
31
|
+
|
|
32
|
+
- `COAIA_MEDIA_MAX_BYTES`: maximum downloaded file size; defaults to 10 MiB.
|
|
33
|
+
- `COAIA_OPENAI_FILE_HOSTS`: comma-separated additional trusted conversation-file hosts.
|
|
34
|
+
- `COAIA_MEDIA_UPLOAD_HOSTS`: comma-separated additional trusted presigned-upload hosts for self-hosted storage.
|
|
35
|
+
- `COAIA_MEDIA_ALLOW_HTTP=true`: allows HTTP for local tests only; never use it in production.
|
|
36
|
+
|
|
37
|
+
The proxy only downloads from approved OpenAI file hosts and only uploads to approved S3-compatible storage hosts. It rejects empty files, invalid media contexts, oversized payloads, and untrusted URLs.
|
|
38
|
+
|
|
39
|
+
## Configure the Custom GPT
|
|
40
|
+
|
|
41
|
+
1. Replace `https://replace-with-your-proxy.invalid` in `ceremony-media-proxy.yml` with the deployed HTTPS origin.
|
|
42
|
+
2. Import it as a second Action alongside `ceremony-observations.yml`.
|
|
43
|
+
3. Configure API Key authentication with:
|
|
44
|
+
- Header: `X-Coaia-Proxy-Key`
|
|
45
|
+
- Value: the `COAIA_MEDIA_PROXY_API_KEY` configured on the service
|
|
46
|
+
4. Keep `x-openai-isConsequential: false` unchanged.
|
|
47
|
+
5. Do not put the proxy key or Langfuse keys in GPT instructions or conversation text.
|
|
48
|
+
|
|
49
|
+
## GPT behavior
|
|
50
|
+
|
|
51
|
+
Add this to the GPT instructions:
|
|
52
|
+
|
|
53
|
+
```markdown
|
|
54
|
+
When the user supplies media for Langfuse, call media_uploadConversationFile
|
|
55
|
+
with exactly that conversation file in openaiFileIdRefs and the target trace or
|
|
56
|
+
dataset-item context. Never create placeholder bytes unless explicitly asked.
|
|
57
|
+
|
|
58
|
+
The bridge performs media-record creation, exact-byte hashing, the presigned PUT,
|
|
59
|
+
and media finalization. Do not claim success unless the bridge returns
|
|
60
|
+
success=true and a mediaToken.
|
|
61
|
+
|
|
62
|
+
Put the returned mediaToken unchanged into an observation input, output, or
|
|
63
|
+
metadata value, then call observations_export. Optionally call media_get with
|
|
64
|
+
the returned mediaId to verify uploadedAt and the temporary URL.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Completed flow
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
user/DALL-E/Code Interpreter file
|
|
71
|
+
→ openaiFileIdRefs temporary download URL
|
|
72
|
+
→ media_uploadConversationFile
|
|
73
|
+
→ download exact bytes
|
|
74
|
+
→ compute padded Base64 SHA-256 and exact length/type
|
|
75
|
+
→ POST /api/public/media
|
|
76
|
+
→ PUT exact bytes to the presigned storage URL
|
|
77
|
+
→ PATCH /api/public/media/{mediaId}
|
|
78
|
+
→ return @@@langfuseMedia:type=...|id=...|source=bytes@@@
|
|
79
|
+
→ observations_export containing the returned media token
|
|
80
|
+
→ observations_list / media_get verification
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Primary references:
|
|
84
|
+
|
|
85
|
+
- OpenAI GPT Actions file transfer: https://developers.openai.com/api/docs/actions/sending-files
|
|
86
|
+
- Langfuse multi-modality and media tokens: https://langfuse.com/docs/observability/features/multi-modality
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
openapi: 3.1.0
|
|
2
|
+
info:
|
|
3
|
+
title: Coaia Langfuse Media Upload Bridge
|
|
4
|
+
version: 0.4.2
|
|
5
|
+
description: >-
|
|
6
|
+
Companion Custom GPT action that transfers one conversation file into Langfuse object storage, finalizes the media
|
|
7
|
+
record, and returns a renderable Langfuse media token. Deploy coaiajs-media-proxy and replace the example server URL.
|
|
8
|
+
license:
|
|
9
|
+
name: MIT
|
|
10
|
+
identifier: MIT
|
|
11
|
+
servers:
|
|
12
|
+
- url: https://replace-with-your-proxy.invalid
|
|
13
|
+
description: Replace with the public HTTPS URL of the deployed coaiajs media proxy.
|
|
14
|
+
security:
|
|
15
|
+
- ProxyApiKey: []
|
|
16
|
+
paths:
|
|
17
|
+
/media/upload:
|
|
18
|
+
post:
|
|
19
|
+
operationId: media_uploadConversationFile
|
|
20
|
+
summary: Upload a conversation file to Langfuse
|
|
21
|
+
description: >-
|
|
22
|
+
Upload exactly one user, DALL-E, or Code Interpreter file. The bridge downloads its exact bytes, computes the
|
|
23
|
+
padded Base64 SHA-256 digest and length, creates the Langfuse record, performs the presigned PUT, finalizes it,
|
|
24
|
+
and returns a media token. Never substitute placeholder bytes.
|
|
25
|
+
requestBody:
|
|
26
|
+
required: true
|
|
27
|
+
content:
|
|
28
|
+
application/json:
|
|
29
|
+
schema:
|
|
30
|
+
$ref: '#/components/schemas/UploadConversationFileRequest'
|
|
31
|
+
responses:
|
|
32
|
+
'200':
|
|
33
|
+
description: Uploaded media and its renderable Langfuse token.
|
|
34
|
+
content:
|
|
35
|
+
application/json:
|
|
36
|
+
schema:
|
|
37
|
+
$ref: '#/components/schemas/UploadConversationFileResponse'
|
|
38
|
+
'400':
|
|
39
|
+
description: Invalid file reference, media context, or downstream upload.
|
|
40
|
+
content:
|
|
41
|
+
application/json:
|
|
42
|
+
schema:
|
|
43
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
44
|
+
'401':
|
|
45
|
+
description: Missing or invalid proxy API key.
|
|
46
|
+
content:
|
|
47
|
+
application/json:
|
|
48
|
+
schema:
|
|
49
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
50
|
+
'413':
|
|
51
|
+
description: File or request exceeds the configured size limit.
|
|
52
|
+
content:
|
|
53
|
+
application/json:
|
|
54
|
+
schema:
|
|
55
|
+
$ref: '#/components/schemas/ErrorResponse'
|
|
56
|
+
x-openai-isConsequential: false
|
|
57
|
+
components:
|
|
58
|
+
securitySchemes:
|
|
59
|
+
ProxyApiKey:
|
|
60
|
+
type: apiKey
|
|
61
|
+
in: header
|
|
62
|
+
name: X-Coaia-Proxy-Key
|
|
63
|
+
description: Configure this value in the GPT Action authentication UI; it must equal COAIA_MEDIA_PROXY_API_KEY.
|
|
64
|
+
schemas:
|
|
65
|
+
UploadConversationFileRequest:
|
|
66
|
+
type: object
|
|
67
|
+
additionalProperties: false
|
|
68
|
+
properties:
|
|
69
|
+
openaiFileIdRefs:
|
|
70
|
+
type: array
|
|
71
|
+
minItems: 1
|
|
72
|
+
maxItems: 1
|
|
73
|
+
items:
|
|
74
|
+
type: string
|
|
75
|
+
description: >-
|
|
76
|
+
Exactly one file from the conversation: the user's actual media, a DALL-E image, or a Code Interpreter
|
|
77
|
+
file. Custom GPT replaces this string entry with its temporary runtime file-reference object.
|
|
78
|
+
traceId:
|
|
79
|
+
type: string
|
|
80
|
+
description: Trace receiving the media. Use either trace context or dataset-item context.
|
|
81
|
+
observationId:
|
|
82
|
+
type: string
|
|
83
|
+
description: Optional observation receiving the media; requires traceId.
|
|
84
|
+
datasetId:
|
|
85
|
+
type: string
|
|
86
|
+
description: Dataset receiving the media; requires datasetItemId and no traceId.
|
|
87
|
+
datasetItemId:
|
|
88
|
+
type: string
|
|
89
|
+
description: Dataset item receiving the media; requires datasetId and no traceId.
|
|
90
|
+
field:
|
|
91
|
+
type: string
|
|
92
|
+
enum:
|
|
93
|
+
- input
|
|
94
|
+
- output
|
|
95
|
+
- expectedOutput
|
|
96
|
+
- metadata
|
|
97
|
+
default: input
|
|
98
|
+
description: Field where the returned media token will be referenced.
|
|
99
|
+
required:
|
|
100
|
+
- openaiFileIdRefs
|
|
101
|
+
UploadConversationFileResponse:
|
|
102
|
+
type: object
|
|
103
|
+
additionalProperties: false
|
|
104
|
+
properties:
|
|
105
|
+
success:
|
|
106
|
+
type: boolean
|
|
107
|
+
mediaId:
|
|
108
|
+
type: string
|
|
109
|
+
mediaToken:
|
|
110
|
+
type: string
|
|
111
|
+
description: Put this exact token in observation input, output, or metadata so Langfuse renders the media.
|
|
112
|
+
fileName:
|
|
113
|
+
type: string
|
|
114
|
+
openaiFileId:
|
|
115
|
+
type: string
|
|
116
|
+
contentType:
|
|
117
|
+
type: string
|
|
118
|
+
contentLength:
|
|
119
|
+
type: integer
|
|
120
|
+
sha256Hash:
|
|
121
|
+
type: string
|
|
122
|
+
minLength: 44
|
|
123
|
+
maxLength: 44
|
|
124
|
+
pattern: '^[A-Za-z0-9+/]{43}=$'
|
|
125
|
+
description: Standard padded Base64 SHA-256 digest of the uploaded bytes.
|
|
126
|
+
traceId:
|
|
127
|
+
type: string
|
|
128
|
+
observationId:
|
|
129
|
+
type: string
|
|
130
|
+
datasetId:
|
|
131
|
+
type: string
|
|
132
|
+
datasetItemId:
|
|
133
|
+
type: string
|
|
134
|
+
field:
|
|
135
|
+
type: string
|
|
136
|
+
uploadTimeMs:
|
|
137
|
+
type: integer
|
|
138
|
+
alreadyUploaded:
|
|
139
|
+
type: boolean
|
|
140
|
+
required:
|
|
141
|
+
- success
|
|
142
|
+
- mediaId
|
|
143
|
+
- mediaToken
|
|
144
|
+
- openaiFileId
|
|
145
|
+
- contentType
|
|
146
|
+
- contentLength
|
|
147
|
+
- sha256Hash
|
|
148
|
+
- field
|
|
149
|
+
- uploadTimeMs
|
|
150
|
+
- alreadyUploaded
|
|
151
|
+
ErrorResponse:
|
|
152
|
+
type: object
|
|
153
|
+
additionalProperties: false
|
|
154
|
+
properties:
|
|
155
|
+
error:
|
|
156
|
+
type: string
|
|
157
|
+
required:
|
|
158
|
+
- error
|
|
@@ -10,7 +10,6 @@ Langfuse v4 does not provide mutable REST trace and observation creation endpoin
|
|
|
10
10
|
POST /api/public/otel/v1/traces
|
|
11
11
|
Content-Type: application/json
|
|
12
12
|
Authorization: Basic <base64(public-key:secret-key)>
|
|
13
|
-
x-langfuse-ingestion-version: 4
|
|
14
13
|
```
|
|
15
14
|
|
|
16
15
|
The `observations_export` action exposes that endpoint with a constrained OTLP schema and examples. It supports both:
|
|
@@ -18,7 +17,7 @@ The `observations_export` action exposes that endpoint with a constrained OTLP s
|
|
|
18
17
|
1. Creating a trace by sending a root span without `parentSpanId`.
|
|
19
18
|
2. Appending an observation by reusing the trace ID and setting `parentSpanId` to an existing observation/span ID.
|
|
20
19
|
|
|
21
|
-
The file has **
|
|
20
|
+
The file has **23 actions**, below the stated 30-action limit. Scores and the original media operations remain in this specification because the complete focused surface still fits. Destructive delete actions are omitted.
|
|
22
21
|
|
|
23
22
|
## Configure the Custom GPT
|
|
24
23
|
|
|
@@ -44,7 +43,7 @@ The file has **20 actions**, below the stated 30-action limit. Scores remain in
|
|
|
44
43
|
end_ns = max(time.time_ns(), start_ns)
|
|
45
44
|
```
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
Custom GPT currently ignores ordinary OpenAPI header parameters, so this direct specification intentionally does not declare `x-langfuse-ingestion-version`. Langfuse documents that OTLP ingestion without that header still works, but data may take up to ten minutes to appear in v4 reads. If real-time visibility is mandatory, use a trusted proxy that adds `x-langfuse-ingestion-version: 4` before forwarding the request to Langfuse.
|
|
48
47
|
|
|
49
48
|
## Recommended GPT instructions
|
|
50
49
|
|
|
@@ -80,6 +79,19 @@ span. To record a correction or later result, append a new child event/span.
|
|
|
80
79
|
After exporting, call observations_list with the traceId and fields
|
|
81
80
|
core,basic,time,io,metadata,model,usage,trace_context to verify the hierarchy.
|
|
82
81
|
Use each returned observation id as the span/parent ID for later children.
|
|
82
|
+
|
|
83
|
+
### Langfuse media
|
|
84
|
+
|
|
85
|
+
When the user supplies media, use the actual file bytes—never placeholder text.
|
|
86
|
+
Compute contentLength from those bytes. Compute SHA-256 over those bytes and
|
|
87
|
+
send the standard padded Base64 digest, not hexadecimal, as sha256Hash.
|
|
88
|
+
|
|
89
|
+
Prefer media_uploadConversationFile from the companion proxy Action; pass the
|
|
90
|
+
user's actual conversation file in openaiFileIdRefs. It performs record
|
|
91
|
+
creation, the exact-byte PUT, and finalization and returns a mediaToken.
|
|
92
|
+
|
|
93
|
+
media_getUploadUrl alone only creates a record. Never claim success without a
|
|
94
|
+
completed PUT and media_patch, or success=true from the proxy bridge.
|
|
83
95
|
```
|
|
84
96
|
|
|
85
97
|
## Minimal append example
|
|
@@ -102,7 +114,7 @@ The parent trace and root observation must already exist. Replace every example
|
|
|
102
114
|
{
|
|
103
115
|
"scope": {
|
|
104
116
|
"name": "custom-gpt-ceremony",
|
|
105
|
-
"version": "0.4.
|
|
117
|
+
"version": "0.4.2"
|
|
106
118
|
},
|
|
107
119
|
"spans": [
|
|
108
120
|
{
|
|
@@ -151,7 +163,28 @@ The parent trace and root observation must already exist. Replace every example
|
|
|
151
163
|
| Datasets and dataset items | 6 |
|
|
152
164
|
| Scores and score configurations | 5 |
|
|
153
165
|
| Comments | 2 |
|
|
154
|
-
|
|
|
166
|
+
| Media | 3 |
|
|
167
|
+
| **Total** | **23** |
|
|
168
|
+
|
|
169
|
+
## Media workflow
|
|
170
|
+
|
|
171
|
+
When the user supplies media, always use that media's actual bytes. Never create or hash placeholder text or surrogate bytes unless the user explicitly requests a placeholder.
|
|
172
|
+
|
|
173
|
+
1. Read the exact bytes that will be uploaded.
|
|
174
|
+
2. Derive `contentType` from those bytes/file and set `contentLength` to their exact byte length.
|
|
175
|
+
3. Compute SHA-256 over those exact bytes, then encode the 32-byte digest with standard padded RFC 4648 Base64. Send the resulting 44-character value as `sha256Hash`; never send the 64-character hexadecimal digest.
|
|
176
|
+
4. Call `media_getUploadUrl` with the context, file metadata, Base64 hash, and field.
|
|
177
|
+
5. PUT the same exact bytes to the returned presigned `uploadUrl` using the declared content type.
|
|
178
|
+
6. Only after that PUT completes, call `media_patch` with the completion time and HTTP result.
|
|
179
|
+
7. Optionally call `media_get` to verify the media record and obtain a temporary download URL.
|
|
180
|
+
|
|
181
|
+
Example for the four UTF-8 bytes `test`:
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
sha256Hash: n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Receiving `uploadUrl` creates a Langfuse media record but does **not** upload the bytes. Never report that media was uploaded after `media_getUploadUrl` alone. The direct OpenAPI document cannot describe a PUT to a dynamically returned storage host. For autonomous uploads, deploy the included `coaiajs-media-proxy`, import `ceremony-media-proxy.yml` as a second GPT Action, and use `media_uploadConversationFile`. The bridge consumes the user's actual `openaiFileIdRefs` file, performs the complete upload flow, and returns the media token.
|
|
155
188
|
|
|
156
189
|
## Why there are not separate create-trace and append-observation actions
|
|
157
190
|
|