Writing Scripts with 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/
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:
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)
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 fieldfield_values_df
: (Optional) DataFrame with initial field values for created entities. If a column is called 'title' or 'Title', it will set the entities' titlesnumber_of_empty_entities
: (Optional) Number of blank entities to create in addition to any entities from the DataFrametype_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 fromtitle
: (Required, keyword-only) Title for the new templateinitial_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 fromversion
: (Optional, keyword-only) Specific version of the templatefield_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 fieldtype_or_template_ref
: Entity reference object pointing to either a type or templateFor 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 instancetitle
:The name for the charttype_title
: The name of the type to create a chart from. The content type must beChart.
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 runversion
: (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 scriptsversion
: (Optional, keyword-only) Specific version of the entitycard_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).
Getting live backlinks
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 agentfile_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.
Last updated