- Updated dependencies to remediate known security vulnerabilities.
Notable additions, fixes, or breaking changes to the Freeplay SDK.
- Minimum Python version raised to 3.10: Python 3.8 and 3.9 are no longer supported and have been EOL'd by Python Software Foundation.
- Minimum
requestsversion raised to 2.33.0: Previously 2.20.0.
- Pinned transitive dependencies (
protobuf,pyasn1,urllib3) to address security vulnerabilities.
- History support without explicit placeholder:
TemplatePrompt.bind()now acceptshistoryeven when the prompt template does not contain a history placeholder. The history messages are appended after the template messages.
- Test run status:
TestRunResultsnow includes astatusfield ("complete","in-progress","failed", orNone) from the Get Test Run Results API.
FormattedPrompt.all_messages()— usellm_promptwith completion output directly when constructingRecordPayload.
openai_responsesadapter: Content blocks now use Responses API native types (input_text,input_image,input_file) instead of Chat Completions types (text,image_url,file) which OpenAI rejects.
toolrole support for OpenAI adapters:OpenAIAdapterandOpenAIResponsesAdapternow accepttoolrole messages in history. Previously, tool-use conversation history would crash withValueError: role 'tool' is not supported.
openai_responsesflavor: New adapter for the OpenAI Responses API.developerrole support: Messages withrole: "developer"are now supported. Each adapter coerces the role appropriately for its provider — e.g. mapped tosystemfor providers that don't support it natively, preserved as-is for OpenAI flavors.
- Added automatic retries for read failures on HTTP requests.
- Added automatic retries for transient connection failures on HTTP requests.
-
gemini_api_chatflavor: New flavor for the Gemini API (google-generativeaiSDK). Returns plain-dict tool schemas compatible withgoogle.genai, whilegemini_chatcontinues to returnvertexai.generative_models.Toolobjects for Vertex AI users. -
Gemini message parts passthrough: History messages already in Gemini format (with
parts, e.g., function calls and function responses) are now passed through without re-wrapping. Role"assistant"is automatically translated to"model". -
Interactive REPL for development and testing:
make repl- Production mode (connects to app.freeplay.ai with SSL verification enabled)make repl-local- Local development mode (connects to localhost:8000 with SSL verification disabled)- Pre-loaded imports (Freeplay client, etc.)
- Environment variables automatically loaded from
.envfile - Pre-initialized
clientvariable ready to use
-
Tool Schema Handling: The SDK no longer provides
GenaiFunctionandGenaiToolwrapper types. Tool schemas should be passed directly as dictionaries in the provider's native format (e.g., fromgoogle-generativeaiorvertexaiSDKs). This aligns with how messages are handled - users pass provider-native types directly to Freeplay.# Tool schemas are now passed as raw dictionaries # matching the provider's format tool_schema = [ { "functionDeclarations": [ { "name": "get_weather", "description": "Get the current weather for a location", "parameters": { "type": "object", "properties": { "location": {"type": "string", "description": "City name"}, "units": { "type": "string", "enum": ["celsius", "fahrenheit"], "description": "Temperature units" } }, "required": ["location"] } } ] } ] # Use in recordings client.recordings.create( RecordPayload( project_id=project_id, all_messages=[...], tool_schema=tool_schema, call_info=CallInfo(provider="vertex", model="gemini-2.0-flash") ) )
Notes:
- Backend automatically normalizes all tool schema formats (OpenAI, Anthropic, GenAI/Vertex)
- No breaking changes to the API - tool schemas are still passed the same way
- This approach is consistent with how we handle messages from different providers
- Fixed broken links in README when viewed on PyPI (CHANGELOG, CONTRIBUTING, LICENSE now use absolute GitHub URLs)
- License changed from MIT to Apache-2.0
-
New
Metadataresource for updating session and trace metadata after creation:# Update session metadata fp_client.metadata.update_session( project_id=project_id, session_id=session_id, metadata={"customer_id": "cust_123", "rating": 5} ) # Update trace metadata fp_client.metadata.update_trace( project_id=project_id, session_id=session_id, trace_id=trace_id, metadata={"resolved": True, "resolution_time_ms": 1234} )
This addresses the use case where IDs or metadata are generated at the end of a conversation and need to be associated with existing sessions/traces without logging additional completions. Metadata updates use merge semantics - new keys overwrite existing keys while preserving unmentioned keys.
- New examples around multimodal images as output
- Get test cases and output_message which may be more than just text content. 'output' is now deprecated.
- Add explicit tool span logging
- Remove image and file restriction for Bedrock Converse.
-
New
parent_idparameter inRecordPayloadto replace the deprecatedtrace_infoparameter. This UUID field enables direct parent-child trace/completions relationships:# Before (deprecated): RecordPayload( project_id=project_id, all_messages=messages, trace_info=trace_info ) # After: RecordPayload( project_id=project_id, all_messages=messages, parent_id=parent_id # UUID of parent trace or completion )
-
parent_idparameter support inSession.create_trace():parent_trace = session.create_trace(input="Parent question", agent_name="parent_agent") child_trace = session.create_trace( input="Child question", agent_name="child_agent", parent_id=uuid.UUID(parent_trace.trace_id) # Or it can be an ID of a completion )
-
parent_idparameter inSession.restore_trace()method
RecordPayload.trace_infoparameter is deprecated and will be removed in v0.6.0. Useparent_idinstead for trace hierarchy management.
-
RecordPayloadnow requiresproject_idas the first parameter. All code creatingRecordPayloadinstances must be updated to include this field. -
PromptInfono longer contains aproject_idfield. The project ID must now be accessed from the project context instead. -
RecordPayload.prompt_infofield has been renamed toRecordPayload.prompt_version_infoand now acceptsPromptVersionInfoobjects. ExistingPromptInfoobjects can still be passed, but the field name must be updated:# Before: RecordPayload( project_id=project_id, all_messages=messages, prompt_info=formatted_prompt.prompt_info ) # After: RecordPayload( project_id=project_id, all_messages=messages, prompt_version_info=formatted_prompt.prompt_info )
-
New
PromptVersionInfoclass that provides lightweight prompt version information with onlyprompt_template_version_idand optionalenvironmentfields.PromptInfonow inherits from this class. -
Support for Vertex AI tool calling. Example:
from vertexai.generative_models import GenerativeModel # Get formatted prompt with tool schema formatted_prompt = fp_client.prompts.get( project_id=project_id, template_name='my-prompt', environment='latest' ).bind(input_variables).format() # Tool schema automatically converted to Vertex AI format model = GenerativeModel( model_name=formatted_prompt.prompt_info.model, tools=formatted_prompt.tool_schema # Returns list[Tool] for Vertex AI )
-
Add new optional field
target_evaluation_idstoTestRuns.create()to control which evaluations run as part of a test. -
Test cases created via
createorcreate_manymay now specifymedia_inputsto programmatically create test cases with images, audio, and other files.
- In
RecordPayload, the following fields are now optional:inputs(Optional)prompt_version_info(Optional, renamed fromprompt_info)call_info(Optional)
session_infoinRecordPayloadnow has a default value and will be automatically generated if not provided.
- Create a test run from the SDK with test cases with media in them.
customer_feedback.update_customer_feedback()now requires a project_id parameter.
- New
download-allCLI command that downloads all prompts across all projects within an account for bundling. Example:This command automatically downloads all of prompts from all projects tagged with the given environment.freeplay download-all --environment latest --output-dir ./prompts
- Create test run with dataset that targets agent. Example:
test_run = fp_client.test_runs.create( project_id, "Dataset Name", include_outputs=True, name="Test run title", description='Some description', flavor_name=template_prompt.prompt_info.flavor_name )
- Use traces when creating test run. Example:
trace_info.record_output( project_id, completion.choices[0].message.content, { 'f1-score': 0.48, 'is_non_empty': True }, test_run_info=test_run.get_test_run_info(test_case.id) )
- Renamed
TestCasedataclass toCompletionTestCasedataclass. The oldTestCaseis still exported asTestCasefor backwards-compatibility, but is deprecated. - Both
CompletionTestCaseandTraceTestCasenow surfacecustom_metadatafield if it was supplied when the dataset was built.
- Allow passing provider specific messages in Gemini so history works.
- Add support for Amazon Bedrock Converse flavor
- Updated "click" project dependency to support newer minor and patch versions.
- Added support for files and audio in prompt templates.
- Added support for images in prompt templates. Prompt templates created with media slots can be formatted using the Python SDK and sent as images to LLM providers using the media_inputs parameter:
self.freeplay_thin.prompts.get_formatted(
project_id=self.project_id,
template_name=template_name,
environment=tag if tag else self.tag,
variables=input_variables,
media_inputs=media_inputs,
)
Future releases will include file inputs and audio inputs.
- Enhanced agent support
Session.create_tracenow accepts:agent_name: used to name a "type" of trace and identify associated traces in the UI.custom_metadata: used for logging of metadata from your execution environment. level like it is today.
TraceInfo.record_outputnow accepts:eval_results: used to record evaluations similar to the output recorded on a completion.
- Added handling of prompt formatting for Perplexity models.