Seal allows you to write and execute your own custom Python code within the platform, enabling powerful custom solutions and automations. Scripts can contain code that can be then executed. This is useful for automating data transformation and creation. For example, scripts can ingest a machine output CSV file, do some data cleaning and other transformation, and store the results in Seal as Records. Scripts enable you to transform your data in more powerful and flexible ways.

Using Scripts in Seal

Scripts can be ran as standalone entities, or ran within other entities from a ‘Script’ field. When run from within another entity, scripts are able to look at the context of the entity they are ran from. This allows them to read from and write edits to these entities.

Triggers

What is a Trigger?

  • A trigger is something that lives on a script, and automatically runs that script at a particular event.
  • These triggering events can be
    • Event based: This means they have been caused by edits or changes to particular entities
    • Time based: eg. every 5 minutes

How to set up a Trigger

Navigate to the script that you want to be triggered. In the right hand side bar, you will see a ‘Triggers’ tab. From there, you can view and remove existing triggers, as well as creating new ones. Screen Cast 2025-08-28 at 11.31.52 PM.gif You can view (but not edit) all existing triggers from the organisation settings page. For each trigger here you can see:
  • what event will trigger it
  • what script it applies to
  • all runs of the trigger, their status, timings and logs
Screen Cast 2025-08-28 at 11.32.44 PM.gif In the audit log, the ‘user’ who runs the script and is responsible for any of the scripts actions will be the ‘trigger runner’. Screenshot 2025-08-28 at 23.33.52.png

Different Trigger Events

Entity dependent:

These events all relate to changes to certain entities, you can pick which entities classify when you make the event. Screenshot 2025-08-28 at 23.35.32.png
  1. Choose whether you want the trigger to apply to changes to Templates, Instances, or both
  2. Choose specific entities that you want to trigger on.
If you choose ‘INSTANCE’ , but you then select a specific template entity, this means the trigger will apply to all instances of that template. If you choose ‘INSTANCE’ and select an instance, that trigger will only look for trigger events on that singular entity, likewise if you choose ‘TEMPLATE’ and select a template.
Entity dependent eventDescriptionNotes
onMoveOutOfEditableThis will trigger the script to run whenever a chosen entity becomes non-editableThe only way for entities to become ‘non-editable’ are to be sent for review or published
onCreateThis will trigger the script to run when a chosen entity is createdThis trigger will only work when INSTANCE has been chosen, and a specific template selected.
onArchiveThis will trigger the script to run when a chosen entity is archived-
onRecoverThis will trigger the script to run when a chosen entity is recovered-
onMakeEditableThis will trigger the script to run whenever a chosen entity moves from non-editable to editableThis can happen when new drafts are made, when review requests are disapproved or cancelled, or if validation checks fail.
As these triggers are all entity dependent, meaning the script can run with the context of the entity that triggered it. Eg. If the script is to add a tag to the entity, and the trigger is onCreate - every time an entity is created that matches the conditions, the script can tag that particular entity

Entity independent:

Entity independent triggers allow scripts to run autonomously, without being directly tied to a parent entity. These scripts can still interact with and perform actions on various entities, but they operate independently from any specific entity.
NameDescriptionNotes
onScheduleThis will execute the script at predetermined intervals, such as every 5 minutes or at midnight daily.Scheduled times are evaluated in the UTC timezone, ensuring consistent execution regardless of local time variations.
Entity independent scripts are particularly useful for tasks that require regular execution or maintenance, such as cleanup processes or periodic data analysis, without the need for entity-specific context.

Writing Scripts using the Seal Module

The Seal Platform allows you to write and execute your own custom Python code within the platform, enabling powerful custom solutions and automations. If this is your first time using Python, then there are great reference materials online such as: https://docs.python.org/3.10/tutorial/
What if I don’t know how to code?Not to worry - Seal comes with a built in AI Copilot to write code for you. Navigate to the ‘Copilot’ tab on the right hand side, and start chatting with the AI to describe what you need.The AI agent has access to your current code, so you can ask it to help you debug specific issues or add to the existing code.Screenshot 2025-08-28 at 23.18.46.pngOnce you’re happy with the code, click on ‘Accept code’ to use it in your Script.Note that the generated code may not fully be fit for your purpose - we recommend checking over the results.

The Seal Module

The Seal module is a Python package for interacting programatically with the Seal platform. It is automatically available in every Script’s Python environment - you don’t need to import it manually. The Seal module consists of a collection of methods on the seal object:

Getting entities

seal.get_entity(entity_id, ?version)
seal.get_entity(ref={"id: "...", "version": "..."})
Returns the entire json blob of data for that entity. The entity id can be copied from the entity’s URL in Seal - it’s the final section of the url, after the entity title.
Just passing an entity_id returns the latest version or draft of the entity.
The entity id can be copied from the entity’s URL in Seal - it’s the final section of the url, after the entity title. To get a specific version of an entity, include the version as a second argument. You can also pass an entity ref object instead. Since it returns the whole json blob for the entity, you can get the entity’s fields via entity["fields"] , or a specific field via entity["fields"]["fieldName"] .
seal.get_entity_active_version(entity_id)
Gets the data for the active version of the given entity. If no active version is found (ie the entity has never been published), an error will be thrown.
seal.get_containing_entity()
Gets the entity the script card is embedded in.
seal.is_test_entity(entity_id)
Returns a boolean indicating whether or not an entity is a test entity.
seal.is_containing_entity_a_test_entity()
Returns a boolean indicating whether or not the entity the script is embedded is a test entity. Can only be run from a script field.
seal.get_entities_by_title(title)
Gets (non-archived) entities by their title (string). Note that exact titles are matched by default. Since multiple entities can share the same title, this returns an array. You can also search for titles containing the search string with exact=False.
seal.search_entities(query_config)
Gets entities by searching with a query config object (dict). See the API documentation for more details on the query config schema.

Making an entity editable

seal.make_entity_editable(entity_id)
Used to make an entity editable (ie create a new draft). Returns the entire json blob of data for the new draft entity. If the entity is already editable, this will make no changes and return the current draft.

Reverting entity drafts

seal.revert_entities(entity_ids)
Revert multiple entity drafts to their previous published versions. All entities must be in EDITABLE status and have a previous version. Up to 500 entities can be reverted at once. Parameters:
  • entity_ids: List of entity IDs to revert (maximum 500)
Returns an array of the reverted entities.
seal.revert_containing_entity()
Revert the entity the script is embedded in to its previous published version. The entity must be in EDITABLE status and have a previous version. Returns an array containing the reverted entity.

Validating entities

Scripts can be used to run checks before an entity is published. A script can be added as a check on a type or template for its templates or instances.
seal.get_validating_entity()
Gets the entity a script is validating. When a validation script is run, it is classed as passing if no errors are thrown. Any of the following methods will throw an error if the assertion is not met:
MethodChecks that
validation.assertEqual(a, b)a == b
validation.assertNotEqual(a, b)a != b
validation.assertTrue(x)bool(x) is True
validation.assertFalse(x)bool(x) is False
validation.assertIs(a, b)a is b
validation.assertIsNot(a, b)a is not b
validation.assertIsNone(x)x is None
validation.assertIsNotNone(x)x is not None
validation.assertIn(a, b)a in b
validation.assertNotIn(a, b)a not in b
validation.assertIsInstance(a, b)isinstance(a, b)
validation.assertNotIsInstance(a, b)not isinstance(a, b)
User-defined errors can also be thrown to fail a validation script.
seal.throw_error(message)
Throws an error with a user-provided message.

Archiving an entity

seal.archive_entity(entity_id, archive)
Archives or unarchives an entity. The archive parameter should be a boolean: True to archive, False to recover. Returns the updated entity data.
seal.archive_entities(entity_ids)
Archives multiple entities. Must pass in an array of entity_id values. Returns the ids that were archived.

Converting an Instance to a Template

seal.convert_instance_to_template(entity_id)
Converts an instance entity into a template entity. The instance must be editable (a draft) to be converted. Returns the entire json blob of data for the new template entity.

Updating the status tag on an entity

seal.update_entity_status_tag(entity_id, status_tag)
Updates the status tag on an entity. The live entity must be in an editable state.
seal.update_upcoming_entity_status_tag(entity_id, status_tag)
Updates the upcoming status tag an entity will have when it is next published. The live entity must be in an editable state.

Getting the upcoming version info of an entity

seal.get_upcoming_version_info(entity_id)
Returns the upcoming version info of an entity. This includes the version and status tag.

Adding an entity to a change set

seal.add_entity_to_change_set(entity_id, change_set_index)
Used to add an entity to a pre-existing change set. The change_set_index can be found in the URL when on a change set page. Returns information about the change set the provided entity now belongs to. This information includes id, index, name, status and description.

Adding multiple entities to a change set

seal.add_entities_to_change_set(entity_ids, change_set_index)
Used to add multiple entities to a pre-existing change set. The entity_ids parameter should be a list of entity IDs, and the change_set_index can be found in the URL when on a change set page. Returns information about the change set that the provided entities now belong to. This information includes id, index, name, status, description and entityRefs.

Creating Change Sets

seal.create_change_set(entity_ids, ?change_set_name)
Creates a new change set containing the provided entities. Returns information about the created change set including id, index, name, status, description and entityRefs.

Getting tags

seal.get_tags_for_entity(entity_id)
Gets the tags on an entity.
seal.get_tags(tag)
Gets the tags on an entity the script is embedded in. Can only be run from a script card.

Adding tags

seal.add_tag_to_entity(entity_id, tag)
Adds a tag to an entity. If no tag matching the input tag is found in the organisation, a new tag will be created.
seal.add_tag(tag)
Adds a tag to the entity the script is embedded in. Can only be run from a script card.

Deleting tags

seal.delete_tag(tag_name)
Remove a tag by name from the entity within which the script is embedded.
seal.delete_tag_from_entity(entity_id, tag_name)

Sending notification emails

seal.send_email_notification(emails, subject, message, ?entity_id)
Queues notification emails to specified users who are members of your organisation. Emails are sent after the transaction commits and are subject to per-organisation daily limits and content validation. Parameters:
  • emails: list of recipient email addresses (1–100). All recipients must be existing users in your organisation.
  • subject: plain text subject. URLs are not allowed.
  • message: plain text message body. URLs are not allowed.
  • entity_id (optional): entity to link the call-to-action to. If omitted, the button opens your organisation home in Seal.
Returns: Returns a dictionary with confirmation details for queued emails.
{"ok": True, "recipientCount": len(emails)}
Example:
seal.send_email_notification(["user1@seal.run"], "Maintenance", "Tonight 7pm.")
Remove a tag by name in any entity.

Setting active versions

seal.set_active_version_in_entity(entity_id, version)
Set the active version of an entity. Pin the active version to a specific published version, or set to None to unpin and track the latest published version automatically. If the entity has review requirements, a review request will be created automatically.
seal.set_active_version(version)
Set the active version of the entity the script is embedded in. If no version is provided, unpins the active version to track the latest published version automatically. If the entity has review requirements, a review request will be created automatically. Can only be run from a script card.

Setting assignees

seal.set_assignees(entity_id, assignees)
Set the assignees for an entity. The assignees parameter should be a list of strings where each item is either an email address or a user id.

Getting role information

seal.get_role(role_id)
Get information about a role by ID. Roles can represent users, API keys or user groups. Different role types have different information available, e.g. email for users.

Getting workflow tasks

seal.get_workflow_tasks(entity_id, ?entity_version)
Gets all workflow tasks associated with a workflow entity. Returns a list of dictionaries, each representing a full workflow task object. Each task includes a completedAt timestamp if the task has been completed, or null if the task is not completed.
seal.get_workflow_tasks_for_containing_entity()
Gets all workflow tasks for the entity that a script is embedded in. Can only be run from a script card. Each task includes a completedAt timestamp if the task has been completed.

Getting workflows that reference an entity

seal.get_workflows_referencing(entity_id, ?entity_version)
Gets all workflow entities that have tasks referencing the specified entity either as a template or instance. Returns an array of full workflow entities. If no entity version is provided, workflows referencing the draft entity are returned.
seal.get_containing_entity_workflows_referencing()
Gets all workflow entities that have tasks referencing the entity the script is embedded in. Can only be run from a script card. Uses the specific version of the containing entity.

Getting change sets

seal.get_change_set_for_entity(entity_id, ?version)
seal.get_change_set_for_entity(ref={"id": "...", "version": "..."})
Returns information about the change set the given entity belongs to. This information includes id, index, name, status and description. By default, we find the change set for the latest draft of the entity (if it exists). To find the change set that a specific version of an entity belongs to, include the version as a second argument. You can also pass an entity ref object instead.
seal.get_change_set_for_containing_entity()
Gets the change set for the entity that a script is embedded in. Can only be run from a script card.

Adding fields

seal.add_field(field_name, field_type, value, allow_multiple, select_options, multi_line, formula_expression)
Add a new field to the embedded-in entity. For specific field types, refer to this specific section in the Scripts docs.
seal.add_field_to_entity(entity_id, field_name, field_type, value, allow_multiple, select_options, multi_line, formula_expression)
Add a new field to any entity.

Updating fields

seal.update_field_value(field_name, field_value)
Update a field value in the entity the script is embedded in. Can only be run from a script card.
seal.update_field_value_in_entity(entity_id, field_name, field_value)
Update a field value in any entity.

Deleting fields

seal.delete_field(field_name)
Remove a field from the embedded-in entity. Note that the field’s data will also be removed.
seal.delete_field_in_entity(entity_id, field_name)
Delete field in any entity.

Renaming fields

seal.rename_field(field_name, new_field_name)
Rename a field in the entity the script is embedded in. Can only be run from a script card.
seal.rename_field_in_entity(entity_id, field_name, new_field_name)
Rename a field in any entity.

Adding fields to page content

seal.add_fields_to_page_content(field_names)
Add field cards to the page content of the entity the script is embedded in. All field elements will be appended to the page in the order they are specified.
seal.add_fields_to_page_content_in_entity(entity_id, field_names)
Append field cards to the page content of any entity. All field elements will be appended to the page in the order they are specified.

Deleting fields from page content

seal.delete_fields_from_page_content(field_names)
Delete all instances of these field cards from the page content of the entity the script is embedded in.
seal.delete_fields_from_page_content_in_entity(entity_id, field_names)
Delete all instances of these field cards from the page content of any entity.

Updating properties

seal.update_entity_title(entity_id, title, ?overwrite_computed_title)
Update the title of any entity. If overwrite_computed_title is set to True and the instance has a computed title, this will be overwritten.
seal.update_containing_entity_title(title, ?overwrite_computed_title)
Update the title of the entity the script is embedded in. Can only be run from a script card.

Getting out of spec fields

seal.get_out_of_spec_fields(entity_id, ?version)
seal.get_out_of_spec_fields(ref={"id: "...", "version": "..."})
Gets the out of spec fields for the provided entity. By default, the latest version or draft of the entity is used. To view the out of spec fields from a specific version of an entity, include the version as a second argument. You can also pass an entity ref object instead.

Handling files

seal.download_file(file_entity_id, ?version)
The file is downloaded to the local filesystem of the virtual machine instance.
The value returned is the local file path as a string.
seal.upload_file(file_path, file_name, type_title, template_ref)
Uploads a file into a new entity. The provided type must have ‘File’ content type.
template_ref is optional. If not provided, the file will be created from the type’s default template if it exists.
Returns the entire json blob of data of the new entity.

Submitting Data

seal.submit_to_instance_submission_field(
   "field_name",
   field_values_df=pd.DataFrame([{ "field": "value", "Title": 'title'}]),
   number_of_empty_instances=3
   template_ref={"id": "...", "version": "..."}
)
Submit instances to a submission field in the surrounding entity. Submit one or more instances to an instance submission field, with optional initial field values in a dataframe. If a column is called ‘title’ or ‘Title’, it will set the instances’ titles of setting the values of a field called ‘title’ or ‘Title’). You can optionally specify a number of empty instances to create. If the submission field refers to a type, a template_ref to a template of the type must be provided. You can also submit data to a submission table in any entity:
seal.submit_to_instance_submission_field_in_entity(entity_id, ...the same)

Creating Entities from Reference Fields

seal.create_from_reference_field(
   "field_name",
   field_values_df=pd.DataFrame([{"Title": "Entity with data"}]),
   number_of_empty_entities=2,  # Creates 1 entity with data + 2 blank entities
   type_or_template_ref={"id": "template_id", "version": "1"}
)
Create entities from a reference field and automatically add them to the field value. When type_or_template_ref is not provided, the entity is created based on the reference field’s search configuration. Parameters:
  • field_name: Name of the reference field
  • field_values_df: (Optional) DataFrame with initial field values for created entities. If a column is called ‘title’ or ‘Title’, it will set the entities’ titles
  • number_of_empty_entities: (Optional) Number of blank entities to create in addition to any entities from the DataFrame
  • type_or_template_ref: (Optional) Entity reference object pointing to either a type or template:
    • For template references: {"id": "template_uuid", "version": "1"} (creates instances)
    • For type references: {"ref": {"id": "type_uuid"}} (creates templates)
You must provide either field_values_df with data, number_of_empty_entities, or both. You can also create entities from a reference field in any entity:
seal.create_from_reference_field_in_entity(entity_id, ...the same)

Submission Placeholder Columns

Placeholder columns are additional fields that can be added to all rows in a submission table. These columns are automatically added to existing instances in the submission field.
seal.add_placeholder_column_to_submission_field(field_name, column_name, column_type)
Add a placeholder column to an instance submission field in the entity the script is embedded in. Can only be run from a script card.
seal.add_placeholder_column_to_submission_field_in_entity(entity_id, field_name, column_name, column_type)
Add a placeholder column to an instance submission field in any entity.
seal.update_placeholder_column_config(field_name, column_name, *, allow_multiple=None, select_options=None, multi_line=None, format=None)
Update the configuration of a placeholder column in the entity the script is embedded in. Configuration parameters are keyword-only and optional. Can only be run from a script card.
seal.update_placeholder_column_config_in_entity(entity_id, field_name, column_name, *, allow_multiple=None, select_options=None, multi_line=None, format=None)
Update the configuration of a placeholder column in any entity. Configuration parameters are keyword-only and optional.
seal.remove_placeholder_column_from_submission_field(field_name, column_name)
Remove a placeholder column from an instance submission field in the entity the script is embedded in. Can only be run from a script card.
seal.remove_placeholder_column_from_submission_field_in_entity(entity_id, field_name, column_name)
Remove a placeholder column from an instance submission field in any entity.

Creating Templates

seal.create_template_from_type(
  type_name,
  title='title',
  initial_content_value={ ... }
)
seal.create_template_from_type(
  ref={"id": "...", "version": "..."},
  title='title',
  initial_content_value={ ... }
)
Create a template from a type. This allows you to programmatically create new templates that can then be used to create instances. Parameters:
  • type_name: Name of the type to create a template from
  • title: (Required, keyword-only) Title for the new template
  • initial_content_value: (Optional, keyword-only) Initial content value for the template (for content-based types)

Creating Instances

seal.create_instance_from_template(
  template_id,
  ?version,
  field_values={ "field": "value", ... },
  title='title'
)
seal.create_instance_from_template(
  ref={"id": "...", "version": "..."},
  field_values={ "field": "value", ... },
  title='title'
)
Create an instance from a template. By default, instances are created from the latest published version of the template. To create an instance from a specific version of a template, include the version as a second argument. You can also pass an entity ref object instead. Parameters:
  • template_id: ID of the template to create an instance from
  • version: (Optional, keyword-only) Specific version of the template
  • field_values: (Optional, keyword-only) Initial field values for the instance. The specified fields must exist on the template.
Similarly, you can also create test instances from a template:
seal.create_test_instance_from_template(
  template_id,
  version,
  field_values={ "field": "value", ... },
)

Configuring Instance Submission Fields

# Template reference example (with version)
seal.set_instance_submission_field_config(
  field_name='Imported Data',
  type_or_template_ref={"id": "template_id", "version": "1"}
)

# Type reference example (no version)
seal.set_instance_submission_field_config(
  field_name='Imported Data',
  type_or_template_ref={"ref": {"id": "type_id"}}
)

# For other entities
seal.set_instance_submission_field_config_in_entity(
  entity_id,
  field_name='Imported Data',
  type_or_template_ref={"id": "template_id", "version": "1"}
)
Set the configuration of an instance submission field to point to a specific type or template. This is required before you can submit instances to the field. Parameters:
  • field_name: Name of the instance submission field
  • type_or_template_ref: Entity reference object pointing to either a type or template
    • For template references: {"id": "template_uuid", "version": "1"}
    • For type references: {"ref": {"id": "type_uuid"}}
  • entity_id: (For the _in_entity version) ID of the entity containing the field

Creating Charts

chart = alt.Chart(data).mark_bar().encode(x="x", y="y")
chart_entity_id = seal.create_chart(chart, title="Sample Chart", type_title="Chart", template_ref={"id": "template_id", "version": "1"})
Generate a chart from an Altair chart. Returns the created chart entity_id as a string. See parameters below:\
  • chart: The Altair chart instance
  • title:The name for the chart
  • type_title: The name of the type to create a chart from. The content type must be Chart.
  • template_ref: (Optional) Entity reference object pointing to a template. i.e {"id": "template_uuid", "version": "1"}. If not provided, the chart instance will be created from the type’s default template if it exists.

Running Scripts

seal.run_script(
  script_id,
  ?version
)
seal.run_script(
  ref={"id: "...", "version": "..."},
)
Run an entity that has content type Script code. By default, the latest version of the entity is run. To run a specific version of a script entity, include the version as a second argument. You can also pass an entity ref object instead. Parameters:
  • script_id: ID of the script to run
  • version: (Optional, keyword-only) Specific version of the script
seal.run_embedded_scripts(
  entity_id,
  ?version,
  ?card_ids=["..."]
)
seal.run_embedded_scripts(
  ref={"id: "...", "version": "..."},
  ?card_ids=["..."]
)
Parameters:
  • entity_id: ID of the entity with embedded scripts
  • version: (Optional, keyword-only) Specific version of the entity
  • card_ids: (Optional, keyword-only) List of specific card ids to run on the page
Run all action buttons and script cards embedded in an entity with page content. You can optionally pass in the card_ids argument to specify which scripts in particular should be run. These IDs can be found in the page content of the entity (see the Entity Schema for more details).
seal.get_live_backlinks(entity_id)
Returns the ids of all entities whose live data includes a reference to any version of the requested entity.

Using Neil AI

Note the ai agent must be enabled for your organisation. Contact Seal support to find out more.
seal.call_neil(user_prompt, file_entity_ids=None)
Execute the AI agent in the current context. If called from an embedded script, uses the containing entity’s change set. If called from a standalone script, uses the script entity’s own change set. Parameters:
  • user_prompt: The prompt to send to the AI agent
  • file_entity_ids: (Optional, keyword-only) List of file entity IDs to provide as context. Useful for passing a list of files to generate new entities from
Returns the agent’s text response as a string.
seal.call_neil_in_change_set(user_prompt, change_set_index, file_entity_ids=None)
Execute the AI agent with a user prompt in a specific change set. Additional Parameters:
  • change_set_index: The index of the change set to execute the agent in

Getting trigger info

seal.get_trigger_info()
If the script is being run as a trigger, this method returns an object containing context
about the trigger run: trigger_id and triggered_by_entity_id.

Importing packages

Seal comes with many common Python packages pre-installed. If there are other python packages you regularly require, please contact Seal support. These packages are automatically imported in every Script, so don’t need to be manually imported: Available packages to import include:
  • altair
  • annotated-types
  • attrs
  • blinker
  • cachetools
  • certifi
  • cffi
  • charset-normalizer
  • click
  • cloudevents
  • contourpy
  • cryptography
  • cycler
  • deprecation
  • et-xmlfile
  • flask
  • fonttools
  • functions-framework
  • gcloud
  • google-api-core
  • google-auth
  • google-cloud-appengine-logging
  • google-cloud-audit-log
  • google-cloud-core
  • google-cloud-error-reporting
  • google-cloud-logging
  • google-cloud-storage
  • google-crc32c
  • google-resumable-media
  • googleapis-common-protos
  • grpc-google-iam-v1
  • grpcio
  • grpcio-status
  • gunicorn
  • httplib2
  • idna
  • itsdangerous
  • jinja2
  • joblib
  • jsonschema
  • jsonschema-specifications
  • jwcrypto
  • kiwisolver
  • lxml
  • markupsafe
  • matplotlib
  • numpy
  • oauth2client
  • openpyxl
  • packaging
  • pandas
  • pillow
  • proto-plus
  • protobuf
  • pyasn1
  • pyasn1-modules
  • pycorn
  • pycparser
  • pycryptodome
  • pydantic
  • pydantic-core
  • pyparsing
  • pyrebase4
  • python-dateutil
  • python-docx
  • python-jwt
  • pytz
  • referencing
  • requests
  • requests-toolbelt
  • rpds-py
  • rsa
  • scikit-learn
  • scipy
  • setuptools
  • six
  • tabulate
  • threadpoolctl
  • toolz
  • typing-extensions
  • urllib3
  • vl-convert-python
  • watchdog
  • werkzeug
  • xlrd
To temporarily install a package when running the script:
import subprocess
subprocess.check_output("pip install {name of package}".split())

Examples

Creating and Linking Charts

This example script would be embedded in an entity containing a SUBMISSION field, with your chart data, and a REFERENCE field to embed the generated chart in.
import pandas as pd
import altair as alt

# Name of the chart entity to create
CHART_TITLE = "Growth Rate"
# Your type entity with content type: 'Chart'
# Find or create the type from org setting -> types
CHART_TYPE_NAME = "Chart"
# The containing entity REFERENCE field to append the generated file entity to
REFERENCE_FIELD_NAME = "Charts"
# Submission field name containing your chart data
SUBMISSION_FIELD_NAME = "Data"
# Submission column name to plot on the X axis
SUBMISSION_X_COLUMN = "Time"
# Submission column name to plot on the Y axis
SUBMISSION_Y_COLUMN = "Growth"

# Extract data from submission field
entity = seal.get_containing_entity()
submission_field = entity["fields"].get(SUBMISSION_FIELD_NAME, {})
submitted_refs = submission_field.get("value", [])

# Collect data from submitted entities
data = []
for ref in submitted_refs:
    submitted_entity = seal.get_entity(ref=ref)
    fields = submitted_entity["fields"]

    timepoint = fields.get(SUBMISSION_X_COLUMN, {}).get("value")
    growth_rate = fields.get(SUBMISSION_Y_COLUMN, {}).get("value")

    if timepoint and growth_rate:
        data.append({SUBMISSION_X_COLUMN: timepoint, SUBMISSION_Y_COLUMN: growth_rate})

# Create DataFrame and chart
df = pd.DataFrame(data)
chart = alt.Chart(df).mark_line(point=True).encode(x=SUBMISSION_X_COLUMN, y=SUBMISSION_Y_COLUMN)

# Create chart entity and link to reference field
chart_id = seal.create_chart(chart, title=CHART_TITLE, type_title=CHART_TYPE)

existing_refs = entity["fields"].get(REFERENCE_FIELD_NAME, {}).get("value", []) or []
updated_refs = existing_refs + [{"id": chart_id, "version": None}]
seal.update_field_value(REFERENCE_FIELD_NAME, updated_refs)

Creating Labels

Create PDF labels from entity data with configurable layouts. This method requires the Label creation blueprint to be installed. To setup this up, see Creating labels blueprint.
seal.create_label_v1()
This script uses the ReportLab PDF Library to create labels with text, barcodes (Code128/Code39/QR), images, and geometric elements. It automatically operates in Preview Mode when embedded in a configuration entity (for testing) or Trigger Mode when triggered by entity updates (for automatic label generation). The configuration is stored in entities with layout elements defined in submission tables.

Field Structure in JSON

Fields are stored as an object called fields, keyed by the unique field names. Every field object has the following fields:
  • id - a unique UUID given to every field, so it can be referenced. When a Data Record is created from a Data Step, it will have the same fields with matching ids
  • the field’s type
  • the field’s dataType (usually the same as the type, but multiple field types may use the same underlying data type). type is how it appears in the UI, dataType refers to the underlying data type
  • value - the actual data. All field values are nullable - they are usually null in Data Steps (unless you want a default value for produced Records), and then populated in Data Records when a lab technician is doing data entry, for example.
  • config - certain field have additional config, for example specifying a number display format, or whether the field can contain multiple values.
For example:
"fields": {
    "CSV file": {
      "id": "f1714b77-d081-4a1e-bfc4-427289fce204",
      "type": "REFERENCE",
      "value": [
        {
          "id": "e9a49732-49a0-4674-b683-c6991fac160a",
          "version": "12"
        }
      ],
      "config": {
        "allowMultiple": false
      },
      "dataType": "ENTITY"
    },
    "Group name": {
      "id": "0519bc74-7086-4ba2-b769-994b62a48945",
      "type": "STRING",
      "value": "A23-Z",
      "config": {},
      "dataType": "STRING"
    },
    "Sample weight": {
      "id": "70c33317-16ae-48b2-9907-fc5112677773",
      "type": "NUMBER",
      "value": 52.3,
      "config": {
        "format": "0.000"
      },
      "dataType": "NUMBER"
    }
  }

Field Types

The columns in the dataframe are converted to fields in each Record. Seal infers the field types based on the data provided:
Data shapeField type
a number or NoneNUMBER
a booleanBOOLEAN
an ISO date stringDATE
an ISO datetime string (must be timezone aware)DATETIME
a plain text stringSTRING
an array of UUID stringsUPLOAD (i.e. an array of File ids)
an array of non-UUID stringsSELECT (a select field aka dropdown)
an array of id, version objectsREFERENCE (an entity reference field)

Title shortcut

If the column name is ‘title’ in the dataframe, Seal will automatically output this as the title of the Record, rather than creating a field called ‘title’.