Legacy Metadata Agent (V0)
Legacy metadata agents (version = 0, the default) use the traditional
agent API with MediaContainer for search results and
MetadataSearchResult objects.
Agent Base Classes
All agents inherit from one of the following base classes. The base class determines what media type the agent handles.
Agent.Movies
Base class for movie metadata agents.
Agent.TV_Shows
Base class for TV show metadata agents.
Agent.Artist
Base class for music artist metadata agents.
Agent.Album
Base class for music album metadata agents.
Agent.Photos
Base class for photo metadata agents.
Agent Class Attributes
All agent base classes share the following class attributes:
Attribute |
Type |
Default |
Description |
|---|---|---|---|
name |
str |
‘Unnamed Agent’ |
Display name of the agent. |
languages |
list[str] |
[] |
List of supported language codes (e.g. |
primary_provider |
bool |
True |
Whether this agent is a primary metadata provider. |
contributes_to |
list[str] or None |
None |
List of agent identifiers this agent contributes to. |
accepts_from |
list[str] or None |
None |
List of agent identifiers this agent accepts contributions from. |
fallback_agent |
str or None |
None |
Identifier of the agent to fall back to. |
persist_stored_files |
bool |
True |
Whether to persist stored media files on disk. |
version |
int |
0 |
Agent version. |
Note
Agent version vs. PlexFrameworkVersion
The version attribute on an agent class controls the agent API style:
version 0 (legacy) —
search()receives a MediaContainer forresultsand you append MetadataSearchResult objects. Ifsearch()accepts atreekeyword argument, the framework switches to ObjectContainer + SearchResult instead (see Using the tree Parameter).version 2 (modern, Artist only) —
search()receives an ObjectContainer forresultsand you add SearchResult objects. Only supported for Agent.Artist.
This is not the same as PlexFrameworkVersion in Info.plist, which
selects the framework bootstrap version (always "2" for modern plug-ins).
See Info.plist keys for details.
search(self, results, media, lang, manual=False, tree=None)
Called when the server needs search results for a media item.
Parameter |
Type |
Description |
|---|---|---|
results |
Container to append results to. Use
|
|
media |
Media.Movie, Media.TV_Show, Media.Artist, Media.Album, etc. |
Media hints object with information from the scanner (name, year, etc.). The concrete type depends on the agent base class. |
lang |
str |
Language code for the search. |
manual |
bool |
True if the user initiated the search manually. |
tree |
MediaTree or None |
Keyword argument. When present in the method signature, the framework switches to modern search objects — see Using the tree Parameter below. |
Optional parameters (passed if the function signature accepts them):
Parameter |
Type |
Description |
|---|---|---|
primary |
bool |
|
Contributing agent attributes — When an agent contributes_to another
agent, the media object in search() also has:
Attribute |
Type |
Description |
|---|---|---|
primary_metadata |
model instance or None |
The primary agent’s existing metadata object (e.g. Movie,
TV_Show, etc.). |
primary_agent |
str or None |
Identifier string of the primary agent. |
Example:
results.Append(MetadataSearchResult(id='123', name='Movie Title', year=2020, score=95, lang=lang))
Results are automatically sorted by year and then by score (descending).
Using the tree Parameter
The framework inspects your search() function signature at startup. If the
method declares a tree keyword argument, the framework automatically
switches to the modern search API for that agent:
resultsis passed as an ObjectContainer instead of a MediaContainer.treereceives a MediaTree built from the database, providing the full file and stream hierarchy for the item.Use
results.add(SearchResult(...))instead ofresults.Append(MetadataSearchResult(...)).SearchResultacceptsid,name,year,score,type, andparentName.
This works for all agent types — Movies, TV Shows, Albums, and Photos — without
changing version. The update() method signature and behaviour are
unaffected.
Example — Movie agent with tree:
class MyMovieAgent(Agent.Movies):
name = 'My Movie Agent'
languages = [Locale.Language.English]
primary_provider = True
def search(self, results, media, lang, manual=False, tree=None):
results.add(SearchResult(
id='12345',
name=media.name,
year=int(media.year),
score=100,
))
def update(self, metadata, media, lang, force=False):
metadata.title = 'Movie Title'
metadata.year = 2020
update(self, metadata, media, lang, force=False)
Called when the server needs metadata for a matched item.
Parameter |
Type |
Description |
|---|---|---|
metadata |
The metadata model instance to populate. The concrete type depends on the agent base class. |
|
media |
Media.Movie, Media.TV_Show, Media.Artist, Media.Album, etc. |
The media information. In |
lang |
str |
Preferred language code. |
force |
bool |
True if the user forced a metadata refresh. |
Optional parameters (passed if the function signature accepts them):
Parameter |
Type |
Description |
|---|---|---|
periodic |
bool |
|
prefs |
dict |
Library section preferences (music agents). Keys include:
|
Example Agent
class MyMovieAgent(Agent.Movies):
name = 'My Movie Agent'
languages = [Locale.Language.English]
primary_provider = True
contributes_to = ['com.plexapp.agents.imdb']
def search(self, results, media, lang):
results.Append(MetadataSearchResult(
id='12345', name=media.name, year=media.year, score=100, lang=lang
))
def update(self, metadata, media, lang):
metadata.title = "Movie Title"
metadata.year = 2020
metadata.summary = "A great movie."
metadata.genres.add("Action")
metadata.directors.new().name = "John Director"
role = metadata.roles.new()
role.name = "Jane Actor"
role.role = "Lead"
role.photo = "https://example.com/photo.jpg"
metadata.posters['poster_url'] = Proxy.Media(
HTTP.Request('https://example.com/poster.jpg').content
)
Media Types
Media types represent the information provided by the scanner for each media
item. In search(), the media parameter is a MediaObject with hint
attributes. In update(), the media parameter is a MediaTree with
file information.
Media.Movie
Attribute |
Type |
Description |
|---|---|---|
name |
str |
The detected movie name. |
year |
str |
The detected year. |
openSubtitlesHash |
str |
Hash for OpenSubtitles lookups. |
duration |
str |
Duration in milliseconds. |
id |
str |
Database ID. |
items |
list[MediaItem] |
Media items with parts/streams. |
Media.TV_Show
Attribute |
Type |
Description |
|---|---|---|
show |
str |
The show name. |
season |
str |
Season number. |
episode |
str |
Episode number. |
name |
str |
Episode name. |
year |
str |
Year. |
duration |
str |
Duration. |
episodic |
bool |
Whether it’s episodic (default True). |
seasons |
dict[str, MediaTree] |
Dict of season indices → season MediaTree objects. |
Each season MediaTree has an episodes dict of episode
indices → episode MediaTree objects. Each episode
MediaTree has an items list of MediaItem.
Media.Artist
Attribute |
Type |
Description |
|---|---|---|
artist |
str |
Artist name. |
album |
str |
Album name. |
track |
str |
Track name. |
index |
str |
Track index. |
albums |
dict[str, MediaTree] |
Dict of album GUIDs → album MediaTree objects. |
Media.Album
Attribute |
Type |
Description |
|---|---|---|
name |
str |
Album name. |
artist |
str |
Artist name. |
album |
str |
Album name. |
track |
str |
Track name. |
index |
str |
Track index. |
parentGUID |
str |
GUID of the parent artist. |
parent_metadata |
Artist or None |
Parent artist’s metadata (loaded from |
tracks |
dict[str, MediaTree] |
Dict of track indices → track MediaTree objects. |
MediaTree
A tree structure representing the hierarchical media structure for a library item. Media objects (e.g. Media.Movie, Media.TV_Show) delegate attribute access to the underlying MediaTree, so properties like items, seasons, and episodes are accessible directly on the media object.
Attribute |
Type |
Description |
|---|---|---|
items |
list[MediaItem] |
Media items at this level of the tree. |
settings |
dict |
Settings associated with this item. |
children |
list[MediaTree] |
Child MediaTree nodes. |
Additional attributes vary by level. For a TV show tree, season-level nodes have an episodes dict, and episode-level nodes have items. All XML attributes from the server are also set as properties (e.g. title, year, originally_available_at).
all_parts() → list[MediaPart]
Returns a flat list of all MediaPart objects owned by this node and all its descendants.
MediaItem
Represents a single media file grouping.
Attribute |
Type |
Description |
|---|---|---|
parts |
list[MediaPart] |
List of media parts. |
MediaPart
Represents a single file of a media item.
Attribute |
Type |
Description |
|---|---|---|
file |
str |
Absolute path to the media file. |
hash |
str |
SHA1 hash of the file. |
size |
long |
File size in bytes. |
streams |
list[MediaStream] |
List of media streams. |
thumbs |
dict-like |
Directory for thumbnail images. Supports |
art |
dict-like |
Directory for art images. Same interface as thumbs. |
subtitles |
dict-like |
Directory for subtitles, keyed by language code. Access: |
openSubtitlesHash |
str |
OpenSubtitles hash (if available). |
MediaStream
Represents a single audio, video, or subtitle stream within a part.
Attribute |
Type |
Description |
|---|---|---|
type |
long |
Stream type: 1 = Video, 2 = Audio, 3 = Subtitle. |
index |
long |
Stream index. |
id |
long |
Stream ID. |
codec |
str |
Codec name. |
language |
str |
Language name. |
languageCode |
str |
ISO 639 language code. |
MetadataSearchResult
A search result object for legacy (V0) agent search() calls. Append
these to the results MediaContainer.
MetadataSearchResult(id, name=None, year=None, score=0, lang=None, thumb=None)
Parameter |
Type |
Description |
|---|---|---|
id |
str |
Unique ID for this result. |
name |
str |
Display name. |
year |
int |
Release year. |
score |
int |
Match score (0–100). |
lang |
str |
|
thumb |
str |
Thumbnail URL. |