Based on https://platform.claude.com/docs/en/build-with-claude/skills-guide#go
Maybe I misunderstood the documentation, but I can't find a way to extract FileID's without manually unmarshalling the output from the raw JSON when streaming.
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log"
"os"
"github.com/anthropics/anthropic-sdk-go"
)
func main() {
client := anthropic.NewClient()
stream := client.Beta.Messages.NewStreaming(context.TODO(), anthropic.BetaMessageNewParams{
Model: "claude-haiku-4-5",
MaxTokens: 4096,
Betas: []anthropic.AnthropicBeta{
"code-execution-2025-08-25",
anthropic.AnthropicBetaSkills2025_10_02,
},
Container: anthropic.BetaMessageNewParamsContainerUnion{
OfContainers: &anthropic.BetaContainerParams{
Skills: []anthropic.BetaSkillParams{
{
Type: anthropic.BetaSkillParamsTypeAnthropic,
SkillID: "pdf",
Version: anthropic.String("latest"),
},
},
},
},
Messages: []anthropic.BetaMessageParam{
anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Create a blank PDF file")),
},
Tools: []anthropic.BetaToolUnionParam{
{OfCodeExecutionTool20250825: &anthropic.BetaCodeExecutionTool20250825Param{}},
},
})
response := anthropic.BetaMessage{}
for stream.Next() {
event := stream.Current()
err := response.Accumulate(event)
if err != nil {
panic(err)
}
switch eventVariant := event.AsAny().(type) {
case anthropic.BetaRawContentBlockDeltaEvent:
switch deltaVariant := eventVariant.Delta.AsAny().(type) {
case anthropic.BetaTextDelta:
print(deltaVariant.Text)
}
}
}
fmt.Println()
os.WriteFile("log.json", []byte(response.RawJSON()), 0600)
// Step 2: Extract file IDs from the response
fileIDs := extractFileIDsStreaming(&response)
// Step 3: Download the file using Files API
for _, fileID := range fileIDs {
fileMetadata, err := client.Beta.Files.GetMetadata(context.TODO(), fileID, anthropic.BetaFileGetMetadataParams{
Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
})
if err != nil {
log.Fatal(err)
}
fileContent, err := client.Beta.Files.Download(context.TODO(), fileID, anthropic.BetaFileDownloadParams{
Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaFilesAPI2025_04_14},
})
if err != nil {
log.Fatal(err)
}
// Step 4: Save to disk
out, err := os.Create(fileMetadata.Filename)
if err != nil {
log.Fatal(err)
}
io.Copy(out, fileContent.Body)
out.Close()
fileContent.Body.Close()
fmt.Printf("Downloaded: %s\n", fileMetadata.Filename)
}
}
type Content struct {
Contents []ofContent `json:"OfContent"`
}
type ofContent struct {
FileID string `json:"file_id"`
}
// Works
func extractFileIDsStreaming(response *anthropic.BetaMessage) []string {
var fileIDs []string
for _, item := range response.Content {
switch v := item.AsAny().(type) {
case anthropic.BetaBashCodeExecutionToolResultBlock:
var content Content
err := json.Unmarshal([]byte(v.Content.JSON.Content.Raw()), &content)
if err != nil {
panic(err)
}
for _, output := range content.Contents {
if output.FileID != "" {
fileIDs = append(fileIDs, output.FileID)
}
}
}
}
return fileIDs
}
// Doesn't work (the example on https://platform.claude.com/docs/en/build-with-claude/skills-guide#go)
func extractFileIDs(response *anthropic.BetaMessage) []string {
var fileIDs []string
for _, item := range response.Content {
switch v := item.AsAny().(type) {
case anthropic.BetaBashCodeExecutionToolResultBlock:
for _, output := range v.Content.Content {
if output.FileID != "" {
fileIDs = append(fileIDs, output.FileID)
}
}
}
}
return fileIDs
}
Based on https://platform.claude.com/docs/en/build-with-claude/skills-guide#go
Maybe I misunderstood the documentation, but I can't find a way to extract FileID's without manually unmarshalling the output from the raw JSON when streaming.